#if (FEATURE_MODE == 0)
/**
 @file sys_usw_efd.c

 @date 2014-10-28

 @version v3.0


*/

/************ctc_warmboot.c****************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "ctc_error.h"
#include "ctc_acl.h"
#include "ctc_spool.h"
#include "ctc_hash.h"
#include "ctc_packet.h"
#include "ctc_dtel.h"
#include "ctc_mirror.h"
#include "ctc_macro.h"
#include "ctc_tdx.h"
#include "sys_usw_common.h"
#include "sys_usw_opf.h"
#include "sys_usw_nexthop_api.h"
#include "sys_usw_dtel.h"
#include "sys_usw_register.h"
#include "sys_usw_eunit.h"
#include "sys_usw_dma.h"
#include "sys_usw_parser.h"
#include "sys_usw_wb_common.h"


#include "drv_api.h"


#define SYS_DTEL_IFA_VER 2
#define SYS_DTEL_IFA_PROTOCOL 253
#define SYS_DTEL_IFA_BASE_HDR_LEN 4
#define SYS_DTEL_IFA_GNS_IS_LNS 0xF
#define SYS_DTEL_IFA_DEFAULT_GNS 0
#define SYS_DTEL_IFA_MAX_GNS 0xF
#define SYS_DTEL_IFA_DEFAULT_MAX_LENGTH 128
#define SYS_DTEL_IFA_DEFAULT_HOP_LIMIT 64
#define SYS_DTEL_IFA_VER_MAX 2
#define SYS_DTEL_IFA_SUPPORT_REQUEST_VECTOR 0x00FF
#define SYS_DTEL_IFA_REQ_VEC_SW_ID 0x01
#define SYS_DTEL_REPORT_CPU_REASON_SUB_QUE_ID 75

#define SYS_DTEL_INT_VER 1
#define SYS_DTEL_INT_VER_MASK 0xF

#define SYS_DTEL_INT_SUPPORT_INS_BITMAP 0x00FF
#define SYS_DTEL_INT_SUPPORT_METADATA_NUM 8
#define SYS_DTEL_INT_MAX_METADATA_INDEX   9  /*DsIntSessionEdit.g[x].intMdataIdx*/
#define SYS_DTEL_INT_OCCUPY_IPE_ACL_LOG_ID  7
#define SYS_DTEL_INT_OCCUPY_EPE_ACL_LOG_ID  2

#define SYS_DTEL_INT_SINK_DEST_NUM      4
#define SYS_DTEL_MAX_INT_REP_HDR_LEN    (4 + 6)

#define SYS_DTEL_INT_LOG_ID_NUM      4
#define SYS_DTEL_INT_SEN_BMP_LEN ((CTC_DTEL_INT_SINK_SESSION_NUM + 31)/CTC_UINT32_BITS)

#define SYS_DTEL_IPV6_HEADER_LEN             40
    
#define SYS_DTEL_INT_EPE_DISCARDTYPE      0x39 /* SYS_AT_DISCARD_EPE_INT_SINK_DIS - SYS_AT_DISCARD_EPE_START */

#define SYS_DTEL_LOCK(lchip)    sal_mutex_lock(p_usw_dtel_master[lchip]->mutex)
#define SYS_DTEL_UNLOCK(lchip)  sal_mutex_unlock(p_usw_dtel_master[lchip]->mutex)

#define SYS_DTEL_SINK_LOCK(lchip)    sal_mutex_lock(p_usw_dtel_master[lchip]->sink_mutex)
#define SYS_DTEL_SINK_UNLOCK(lchip)  sal_mutex_unlock(p_usw_dtel_master[lchip]->sink_mutex)

#define MAX_GEN_PKT_PRE_LEN (SYS_DTEL_MAX_INT_REP_HDR_LEN * sizeof(uint32))

#define SYS_DTEL_INIT_CHECK(lchip)         \
    {                                \
        LCHIP_CHECK(lchip);          \
        if (!p_usw_dtel_master[lchip]) {           \
            return CTC_E_NOT_INIT; } \
    }

#define SYS_DTEL_INT_KEY_DEF    sys_drv_int_hdr_cam_key_t key, mask
#define SYS_DTEL_INT_KEY_INIT   {\
    sal_memset(&key, 0, sizeof(sys_drv_int_hdr_cam_key_t));\
    sal_memset(&mask, 0, sizeof(sys_drv_int_hdr_cam_key_t));\
}
#define SYS_DTEL_INT_KEY_SET(field, cam_key, cam_mask)  {\
    key.field = cam_key;\
    mask.field = cam_mask;\
}
#define SYS_DTEL_INT_CAM_SET(lchip, action) _sys_dtel_set_inthdr_cam(lchip, &key, &mask, &action)

#if (SDK_WORK_PLATFORM == 1)
    #define SYS_USW_DTEL_CRC_LEN  0
#else
    #define SYS_USW_DTEL_CRC_LEN  4
#endif

extern int32
sys_usw_packet_usr_rx_cb(uint8 lchip, ctc_pkt_rx_t* p_pkt_rx);
extern int32
sys_usw_packet_tx(uint8 lchip, ctc_pkt_tx_t* p_pkt_tx);
extern int32
sys_usw_qos_set_shape(uint8 lchip, ctc_qos_shape_t* p_shape);

enum sys_dtel_rep_md_bit_e
{
    SYS_DTEL_REP_MD_BIT_LOCAL_PORT = 0,
    SYS_DTEL_REP_MD_BIT_HOP_LANTENCY,
    SYS_DTEL_REP_MD_BIT_QUEUE_DEPTH,
    SYS_DTEL_REP_MD_BIT_EGS_TIMESTAMP,
    SYS_DTEL_REP_MD_BIT_QUEUE_DROP,
    SYS_DTEL_REP_MD_BIT_EGS_TX_LOAD,
    SYS_DTEL_REP_MD_BIT_NUM
};

enum sys_dtel_int_edit_mode
{
   SYS_INT_EDITMODE_SOURCE_UDPPROBE = 0,
   SYS_INT_EDITMODE_SOURCE_TCPPROBE = 1,
   SYS_INT_EDITMODE_SOURCE_UDPRAW   = 2,
   SYS_INT_EDITMODE_SOURCE_TCPRAW   = 3,
   SYS_INT_EDITMODE_TRANSIT_UDPPROBE = 4,
   SYS_INT_EDITMODE_TRANSIT_TCPPROBE = 5,
   SYS_INT_EDITMODE_TRANSIT_UDPRAW  = 6,
   SYS_INT_EDITMODE_TRANSIT_TCPRAW  = 7,
   SYS_INT_EDITMODE_SINK_UDPPROBE   = 8,
   SYS_INT_EDITMODE_SINK_TCPPROBE   = 9,
   SYS_INT_EDITMODE_SINK_UDPRAW     = 10,
   SYS_INT_EDITMODE_SINK_TCPRAW     = 11
};
enum sys_int_hdr_cam_idx_e
{
    SYS_INT_HDRCAM_IDX_EXCEED_RHC,
    SYS_INT_HDRCAM_IDX_EBIT_EQ_1,
    /*valid int packet process*/
    SYS_INT_HDRCAM_IDX_EXCEED_SINK_LEN,
    SYS_INT_HDRCAM_IDX_EXCEED_REPORT_LEN,
    /*invalid int packet process*/
    SYS_INT_HDRCAM_IDX_CBIT_EQ_1,
    SYS_INT_HDRCAM_IDX_REPBIT_EQ_1,
    SYS_INT_HDRCAM_IDX_REPBIT_EQ_2,
    SYS_INT_HDRCAM_IDX_E2E,
    SYS_INT_HDRCAM_IDX_E2E_TRANSIT, /*probe marker mode undo*/
    SYS_INT_HDRCAM_IDX_BASE_UDP_PROB =  SYS_INT_HDRCAM_IDX_E2E_TRANSIT,
    /*default cancel int op*/
    SYS_INT_HDRCAM_IDX_DEFAULT = 15
};
struct sys_drv_int_hdr_cam_key_s
{
  uint32 rsv:28;
  uint32 intLenThreshold0:1;
  uint32 intLenThreshold1:1;
  uint32 remainHopThreshold:1;
  uint32 zeroField0:1;
  uint32 zeroField1 :1;
  uint32 zeroField2 :1;
  uint32 intEncapType:3;
  uint32 intSessionType:3;
  uint32 intType:8;
  uint32 intVerFlag:16;
};
typedef struct sys_drv_int_hdr_cam_key_s sys_drv_int_hdr_cam_key_t;

struct sys_int_cam_action_s
{
    uint8 cam_idx;

    uint8 session_type;
    uint8 session_id;
    uint8 to_cpu;       /*to cpu mode*/
};
typedef struct sys_int_cam_action_s sys_int_cam_action_t;

#if (HOST_IS_LE == 1)
struct sys_int_hdr_s
{
    uint8  rsv4[2];
    uint8  instruction_bitmap_0;
    uint8  instruction_bitmap_1;

    uint8  remaining_hop_cnt;
    uint8  hop_metadata_len:5;
    uint8  rsv3 :3;
    uint8  rsv2 :7;
    uint8  mbit:1;
    uint8  ebit:1;
    uint8  cbit:1;
    uint8  rep:2;
    uint8  ver:4;

    uint8  rsv1:2;
    uint8  dscp:6;
    uint8  len;
    uint8  rsv0;
    uint8  int_type;
};
typedef struct sys_int_hdr_s sys_int_hdr_t;

struct sys_int_rep_hdr_s
{
    uint32 hw_id        :6;
    uint32 f            :1;
    uint32 q            :1;
    uint32 d            :1;
    uint32 reserved     :6;
    uint32 rep_md_bits  :6;
    uint32 n_prot       :3;
    uint32 length       :4;
    uint32 ver          :4;

    uint32 switch_id;
    uint32 sequence_number;
    uint32 ingress_timestamp;
    uint32 metadata[6];
};
typedef struct sys_int_rep_hdr_s sys_int_rep_hdr_t;
#else
struct sys_int_hdr_s
{
    uint8  instruction_bitmap_1;
    uint8  instruction_bitmap_0;
    uint8  rsv4[2];

    uint8  ver:4;
    uint8  rep:2;
    uint8  cbit:1;
    uint8  ebit:1;
    uint8  mbit:1;
    uint8  rsv2 :7;
    uint8  rsv3 :3;
    uint8  hop_metadata_len:5;
    uint8  remaining_hop_cnt;

    uint8  int_type;
    uint8  rsv0;
    uint8  len;
    uint8  dscp:6;
    uint8  rsv1:2;
};
typedef struct sys_int_hdr_s sys_int_hdr_t;

struct sys_int_rep_hdr_s
{
    uint32 ver          :4;
    uint32 length       :4;
    uint32 n_prot       :3;
    uint32 rep_md_bits  :6;
    uint32 reserved     :6;
    uint32 d            :1;
    uint32 q            :1;
    uint32 f            :1;
    uint32 hw_id        :6;
    
    uint32 switch_id;
    uint32 sequence_number;
    uint32 ingress_timestamp;
    uint32 metadata[6];
};
typedef struct sys_int_rep_hdr_s sys_int_rep_hdr_t;
#endif

struct sys_int_rep_param_s
{
    uint32 nhid[CTC_DTEL_INT_SINK_SESSION_NUM];
    uint8  rep_md_bits[CTC_DTEL_INT_SINK_SESSION_NUM];
    uint8 lchip;
};
typedef struct sys_int_rep_param_s sys_int_rep_param_t;

struct sys_int_sink_dest_s
{
  uint32 nh_id;

  uint32 valid_idx;
};
typedef struct sys_int_sink_dest_s sys_int_sink_dest_t;

struct sys_dtel_ifa_session_s
{
    uint8 node : 4;
    uint8 gns  : 4;
    uint8 max_length;
    uint8 hop_limit;
    uint8 req_vec;
};
typedef struct sys_dtel_ifa_session_s sys_dtel_ifa_session_t;

typedef int32 (*sys_dtel_int_pkt_decode_cb_t)(uint8 lchip, ctc_pkt_rx_t* p_pkt_rx, sys_int_pkt_info_t* int_pkt_info);
struct sys_dtel_master_s
{
   uint32 nhid[CTC_DTEL_INT_SINK_SESSION_NUM];
   uint32 log_en[SYS_DTEL_INT_LOG_ID_NUM][SYS_DTEL_INT_SEN_BMP_LEN];
   uint8  postcard_en;                                      /*postcard enable bitmap for reason*/
   uint8  inband_en;                                      /*inband enable log bmp*/
   uint8  chip_id;                                          /*report local chip id*/
   uint8  rep_md_bits[CTC_DTEL_INT_SINK_SESSION_NUM];       /*report metadata bitmap*/
   uint32 timeout;                                          /*report timeout for inband mode, in ms*/
   uint32 rep_id;                                           /*report sequence number*/
   uint32 switch_id;
   uint32 log_cnt[CTC_BOTH_DIRECTION];
   uint8  ifa_en : 1;
   uint8  ifa_test_en : 1; /*do not need warmboot, internal ifa test switch*/
   uint8  ifa_eunit_en : 1;
   uint8  tsx_mac_stats_en : 1;
   uint8  ifa_ver : 2; /*ifa version*/
   uint8  rsv : 2;
   uint8  ifa_protocol;
   uint16  dscp; /**< [TMM.AT] If bit 15 set$)Ao<?ndicate dscp value to int, else, one bit to int */
   sys_dtel_ifa_session_t* ifa_session;
   sal_mutex_t* mutex;
   sal_mutex_t* sink_mutex;
   sal_sem_t* sink_sem;
   sal_task_t* sink_rep;
   ctc_hash_t* int_rep_info;
   uint32 tix_nh_id[CTC_DTEL_TIX_TYPE_MAX]; /*export tix nexthop id*/
   uint32 tsx_nh_id[CTC_DTEL_TSX_TYPE_MAX]; /*export tsx nexthop id*/
   uint32 tex_nh_id[CTC_DTEL_TEX_TYPE_MAX]; /*export tex nexthop id*/
   sys_dtel_int_pkt_decode_cb_t g_sys_dtel_int_pkt_decode_cb;
};
typedef struct sys_dtel_master_s sys_dtel_master_t;

sys_dtel_master_t* p_usw_dtel_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};

#define SYS_DTEL_IFA_REQ_VEC_ALL (CTC_DTEL_IFA_REQ_VEC_LV1_PORT | CTC_DTEL_IFA_REQ_VEC_HOP_LATENCY \
                                  | CTC_DTEL_IFA_REQ_VEC_QUEUE_INFO | CTC_DTEL_IFA_REQ_VEC_IGS_TS \
                                  | CTC_DTEL_IFA_REQ_VEC_EGS_TS |CTC_DTEL_IFA_REQ_VEC_EPTU)

STATIC int32
_sys_dtel_mapping_log_percent(uint8 lchip, uint8 log_percent ,uint32* random_threshold)
{
    switch(log_percent)
    {
    case CTC_LOG_PERCENT_POWER_NEGATIVE_14:     /**< [GB.GG.D2.TM] 2 (-14) */
        *random_threshold = 2;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_13:     /**< [GB.GG.D2.TM] 2 (-13) */
        *random_threshold = 4;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_12:     /**< [GB.GG.D2.TM] 2 (-12) */
        *random_threshold = 8;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_11:     /**< [GB.GG.D2.TM] 2 (-11) */
        *random_threshold = 16;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_10:     /**< [GB.GG.D2.TM] 2 (-10) */
        *random_threshold = 32;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_9:      /**< [GB.GG.D2.TM] 2 (-9)  */
        *random_threshold = 64;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_8:      /**< [GB.GG.D2.TM] 2 (-8)  */
        *random_threshold = 128;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_7:      /**< [GB.GG.D2.TM] 2 (-7)  */
        *random_threshold = 256;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_6:      /**< [GB.GG.D2.TM] 2 (-6)  */
        *random_threshold = 512;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_5:      /**< [GB.GG.D2.TM] 2 (-5) : */
        *random_threshold = 1024;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_4:      /**< [GB.GG.D2.TM] 2 (-4) : 1/16*/
        *random_threshold = 2048;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_3:      /**< [GB.GG.D2.TM] 2 (-3) : 1/8 */
        *random_threshold = 4096;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_2:      /**< [GB.GG.D2.TM] 2 (-2) : 1/4   */
        *random_threshold = 8192;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_1:      /**< [GB.GG.D2.TM] 2 (-1) : 1/2   */
        *random_threshold = 16384;
        break;
    case CTC_LOG_PERCENT_POWER_NEGATIVE_0:      /**< [GB.GG.D2.TM] 2 (0)  : 1/1  */
        *random_threshold = 32768;
        break;
    default:
        *random_threshold = 0;
        break;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_dtel_unmapping_log_percent(uint8 lchip, uint32 random_threshold, uint8* log_percent)
{
    switch(random_threshold)
    {
        case 2:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_14;
            break;
        case 4:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_13;
            break;
        case 8:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_12;
            break;
        case 16:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_11;
            break;
        case 32:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_10;
            break;
        case 64:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_9;
            break;
        case 128:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_8;
            break;
        case 256:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_7;
            break;
        case 512:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_6;
            break;
        case 1024:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_5;
            break;
        case 2048:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_4;
            break;
        case 4096:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_3;
            break;
        case 8192:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_2;
            break;
        case 16384:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_1;
            break;
        case 32768:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_0;
            break;
        default:
            *log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_15;
            break;
    }
    return CTC_E_NONE;
}
STATIC int32
_sys_usw_dtel_add_rep_hash(uint8 lchip, sys_int_pkt_info_t* int_pkt_info, ctc_pkt_rx_t* p_pkt_rx, sys_dtel_pkt_t* p_int_pkt)
{
    int32  ret = CTC_E_NONE;
    uint32 ii = 0;
    uint8* ptr = NULL;
    ctc_pkt_info_t* p_rx_info = &(p_pkt_rx->rx_info);
    sal_systime_t tmp_ts;


    if (NULL == p_int_pkt)  /*add*/
    {
        MALLOC_ZERO(MEM_DTEL_MODULE, p_int_pkt, sizeof(sys_dtel_pkt_t))
        CTC_ERROR_RETURN(NULL == p_int_pkt? CTC_E_NO_MEMORY: CTC_E_NONE);
        p_int_pkt->igs_ts = int_pkt_info->igs_timestamp;
        if (int_pkt_info->from_ipe || int_pkt_info->is_postcard)
        {
            p_int_pkt->session_id = int_pkt_info->int_session;
        }
        p_int_pkt->hash = p_rx_info->hash;
        p_int_pkt->local_src_port = int_pkt_info->from_ipe? p_pkt_rx->rx_info.lport : int_pkt_info->local_src_port;
        if (int_pkt_info->is_postcard)
        {
            p_int_pkt->mode = SYS_DTEL_REP_MODE_DONE;
            sal_memcpy(&p_int_pkt->int_pkt_info, int_pkt_info, sizeof(sys_int_pkt_info_t));
        }
        else
        {
            p_int_pkt->mode = int_pkt_info->from_ipe? SYS_DTEL_REP_MODE_IPE: SYS_DTEL_REP_MODE_EPE;
        }
        sys_usw_get_gchip_id(lchip, &p_int_pkt->chip_id);
        sal_gettime(&tmp_ts);
        p_int_pkt->last_ts = tmp_ts.tv_sec;
        if ((int_pkt_info->is_postcard && !int_pkt_info->from_ipe) || (!int_pkt_info->is_postcard && int_pkt_info->from_ipe))
        {
            p_int_pkt->pkt_buf.len = p_pkt_rx->pkt_len - p_pkt_rx->eth_hdr_len - SYS_USW_PKT_HEADER_LEN;
            p_int_pkt->pkt_buf.data = mem_malloc(MEM_DTEL_MODULE, p_int_pkt->pkt_buf.len + MAX_GEN_PKT_PRE_LEN);
            CTC_ERROR_GOTO(NULL == p_int_pkt->pkt_buf.data? CTC_E_NO_MEMORY: CTC_E_NONE, ret, error0);
            sal_memcpy(p_int_pkt->pkt_buf.data+MAX_GEN_PKT_PRE_LEN, p_pkt_rx->pkt_buf[0].data + p_pkt_rx->eth_hdr_len + SYS_USW_PKT_HEADER_LEN, p_pkt_rx->pkt_buf[0].len - (p_pkt_rx->eth_hdr_len + SYS_USW_PKT_HEADER_LEN));
            ptr = p_int_pkt->pkt_buf.data + MAX_GEN_PKT_PRE_LEN + p_pkt_rx->pkt_buf[0].len - (p_pkt_rx->eth_hdr_len + SYS_USW_PKT_HEADER_LEN);
            for (ii = 1; ii < p_pkt_rx->buf_count; ii++)
            {
                sal_memcpy(ptr, p_pkt_rx->pkt_buf[ii].data, p_pkt_rx->pkt_buf[ii].len);
                ptr += p_pkt_rx->pkt_buf[ii].len;
            }
        }
        if (!int_pkt_info->from_ipe)
        {
            sal_memcpy(&p_int_pkt->pkt_rx, p_pkt_rx, sizeof(ctc_pkt_rx_t));
        }
        if (NULL == ctc_hash_insert(p_usw_dtel_master[lchip]->int_rep_info, (void*)p_int_pkt))
        {
            CTC_ERROR_GOTO(CTC_E_NO_MEMORY, ret, error1);
        }
    }
    else    /*update*/
    {
        p_int_pkt->mode = SYS_DTEL_REP_MODE_DONE;
        sal_gettime(&tmp_ts);
        p_int_pkt->last_ts = tmp_ts.tv_sec;
        if (int_pkt_info->from_ipe)
        {
            p_int_pkt->session_id = int_pkt_info->int_session;
            p_int_pkt->pkt_buf.len = p_pkt_rx->pkt_len - p_pkt_rx->eth_hdr_len - SYS_USW_PKT_HEADER_LEN;
            p_int_pkt->pkt_buf.data = mem_malloc(MEM_DTEL_MODULE, p_int_pkt->pkt_buf.len + MAX_GEN_PKT_PRE_LEN);
            CTC_ERROR_RETURN(NULL == p_int_pkt->pkt_buf.data? CTC_E_NO_MEMORY: CTC_E_NONE);
            sal_memcpy(p_int_pkt->pkt_buf.data+MAX_GEN_PKT_PRE_LEN, p_pkt_rx->pkt_buf[0].data + p_pkt_rx->eth_hdr_len + SYS_USW_PKT_HEADER_LEN, p_pkt_rx->pkt_buf[0].len - (p_pkt_rx->eth_hdr_len + SYS_USW_PKT_HEADER_LEN));
            ptr = p_int_pkt->pkt_buf.data + MAX_GEN_PKT_PRE_LEN + p_pkt_rx->pkt_buf[0].len - (p_pkt_rx->eth_hdr_len + SYS_USW_PKT_HEADER_LEN);
            for (ii = 1; ii < p_pkt_rx->buf_count; ii++)
            {
                sal_memcpy(ptr, p_pkt_rx->pkt_buf[ii].data, p_pkt_rx->pkt_buf[ii].len);
                ptr += p_pkt_rx->pkt_buf[ii].len;
            }
        }
        else
        {
            sal_memcpy(&p_int_pkt->pkt_rx, p_pkt_rx, sizeof(ctc_pkt_rx_t));
            sal_memcpy(&p_int_pkt->int_pkt_info, int_pkt_info, sizeof(sys_int_pkt_info_t));
        }
    }
    return CTC_E_NONE;
error1:
    mem_free(p_int_pkt->pkt_buf.data);
error0:
    mem_free(p_int_pkt);
    return ret;
}


/****************************************************************************
 *
* Defines and Macros
*
*****************************************************************************/

STATIC int32
_sys_dtel_set_inthdr_cam(uint8 lchip, sys_drv_int_hdr_cam_key_t* key, sys_drv_int_hdr_cam_key_t* mask,sys_int_cam_action_t* p_action)
{
    IntHeaderCam_m  int_hdr_cam;
    DsIntHeaderCamAction_m cam_action;
    uint32 cmd = 0;

    sal_memset(&cam_action, 0, sizeof(DsIntHeaderCamAction_m));
    sal_memset(&int_hdr_cam, 0, sizeof(IntHeaderCam_m));

    switch(p_action->session_type)
    {
    case CTC_DTEL_INT_SESSION_TYPE_NONE:
        SetDsIntHeaderCamAction(V, intSessionTypeValid_f, &cam_action, 0);
        break;
    case CTC_DTEL_INT_SESSION_TYPE_CANCEL:
        SetDsIntHeaderCamAction(V, intSessionType_f, &cam_action, 7);
        SetDsIntHeaderCamAction(V, intSessionTypeValid_f, &cam_action, 1);
        break;
    case CTC_DTEL_INT_SESSION_TYPE_SINK:
        SetDsIntHeaderCamAction(V, intSessionType_f, &cam_action, 4);
        SetDsIntHeaderCamAction(V, intSessionTypeValid_f, &cam_action, 1);
        SetDsIntHeaderCamAction(V, intSessionId_f, &cam_action, p_action->session_id);
        break;
    default:
        break;
    }

    switch(p_action->to_cpu)
    {
    case CTC_EXCP_DISCARD_AND_TO_CPU:
        SetDsIntHeaderCamAction(V, exceptionEn_f, &cam_action, 1);
        SetDsIntHeaderCamAction(V, discard_f, &cam_action, 1);
        break;
    case CTC_EXCP_FWD_AND_TO_CPU:
        SetDsIntHeaderCamAction(V, exceptionEn_f, &cam_action, 1);
        SetDsIntHeaderCamAction(V, discard_f, &cam_action, 0);
        break;
    case CTC_EXCP_DISCARD:
        SetDsIntHeaderCamAction(V, exceptionEn_f, &cam_action, 0);
        SetDsIntHeaderCamAction(V, discard_f, &cam_action, 1);
        break;
    case CTC_EXCP_NORMAL_FWD:
    default:
        break;
    }
    cmd = DRV_IOW(DsIntHeaderCamAction_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_action->cam_idx, cmd, &cam_action));

    if ((NULL != key) && (NULL != mask))
    {
        /*cam key*/
        SetIntHeaderCam(V, array_0_fields_intEncapType_f, &int_hdr_cam, key->intEncapType);
        SetIntHeaderCam(V, array_0_fields_intLenThreshold0_f, &int_hdr_cam, key->intLenThreshold0);
        SetIntHeaderCam(V, array_0_fields_intLenThreshold1_f, &int_hdr_cam, key->intLenThreshold1);
        SetIntHeaderCam(V, array_0_fields_intSessionType_f, &int_hdr_cam, key->intSessionType);
        SetIntHeaderCam(V, array_0_fields_intType_f, &int_hdr_cam, key->intType);
        SetIntHeaderCam(V, array_0_fields_intVerFlag_f, &int_hdr_cam, key->intVerFlag);
        SetIntHeaderCam(V, array_0_fields_remainHopThreshold_f, &int_hdr_cam, key->remainHopThreshold);
        SetIntHeaderCam(V, array_0_fields_zeroField0_f, &int_hdr_cam, key->zeroField0);
        SetIntHeaderCam(V, array_0_fields_zeroField1_f, &int_hdr_cam, key->zeroField1);
        SetIntHeaderCam(V, array_0_fields_zeroField2_f, &int_hdr_cam, key->zeroField2);
        /*cam mask*/
        SetIntHeaderCam(V, array_1_fields_intEncapType_f, &int_hdr_cam, mask->intEncapType);
        SetIntHeaderCam(V, array_1_fields_intLenThreshold0_f, &int_hdr_cam, mask->intLenThreshold0);
        SetIntHeaderCam(V, array_1_fields_intLenThreshold1_f, &int_hdr_cam, mask->intLenThreshold1);
        SetIntHeaderCam(V, array_1_fields_intSessionType_f, &int_hdr_cam, mask->intSessionType);
        SetIntHeaderCam(V, array_1_fields_intType_f, &int_hdr_cam, mask->intType);
        SetIntHeaderCam(V, array_1_fields_intVerFlag_f, &int_hdr_cam, mask->intVerFlag);
        SetIntHeaderCam(V, array_1_fields_remainHopThreshold_f, &int_hdr_cam, mask->remainHopThreshold);
        SetIntHeaderCam(V, array_1_fields_zeroField0_f, &int_hdr_cam, mask->zeroField0);
        SetIntHeaderCam(V, array_1_fields_zeroField1_f, &int_hdr_cam, mask->zeroField1);
        SetIntHeaderCam(V, array_1_fields_zeroField2_f, &int_hdr_cam, mask->zeroField2);
        SetIntHeaderCam(V, entryValid_f, &int_hdr_cam, 1);
        cmd = DRV_IOW(IntHeaderCam_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_action->cam_idx, cmd, &int_hdr_cam));
    }
    else if (p_action->cam_idx < SYS_INT_HDRCAM_IDX_BASE_UDP_PROB)
    {
        /*config for udp probe mode actions */
        cmd = DRV_IOR(IntHeaderCam_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_action->cam_idx + SYS_INT_HDRCAM_IDX_BASE_UDP_PROB, cmd, &int_hdr_cam));
        if (GetIntHeaderCam(V, entryValid_f, &int_hdr_cam))
        {
            cmd = DRV_IOW(DsIntHeaderCamAction_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_action->cam_idx + SYS_INT_HDRCAM_IDX_BASE_UDP_PROB, cmd, &cam_action));
        }
    }
    return CTC_E_NONE;

}

STATIC int32
_sys_dtel_clear_inthdr_cam(uint8 lchip)
{
    uint32 idx = 0;
    IntHeaderCam_m  int_hdr_cam;
    DsIntHeaderCamAction_m cam_action;
    uint32 cmd = 0;

    sal_memset(&cam_action, 0, sizeof(DsIntHeaderCamAction_m));
    sal_memset(&int_hdr_cam, 0, sizeof(IntHeaderCam_m));

    for (idx = 0; idx < TABLE_MAX_INDEX(lchip, IntHeaderCam_t); idx++)
    {
        cmd = DRV_IOW(DsIntHeaderCamAction_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, idx, cmd, &cam_action));
        cmd = DRV_IOW(IntHeaderCam_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, idx, cmd, &int_hdr_cam));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_dtel_get_inthdr_cam(uint8 lchip, sys_int_cam_action_t *p_action)
{
    IntHeaderCam_m  int_hdr_cam;
    DsIntHeaderCamAction_m cam_action;
    uint32 cmd = 0;
    uint8   session_type    = 0;
    uint8   session_valid   = 0;
    uint8   exception_en    = 0;
    uint8   discard         = 0;

    sal_memset(&cam_action, 0, sizeof(DsIntHeaderCamAction_m));
    sal_memset(&int_hdr_cam, 0, sizeof(IntHeaderCam_m));

    cmd = DRV_IOR(DsIntHeaderCamAction_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_action->cam_idx, cmd, &cam_action));
    session_valid = GetDsIntHeaderCamAction(V, intSessionTypeValid_f, &cam_action);
    session_type = GetDsIntHeaderCamAction(V, intSessionType_f, &cam_action);

    if (!session_valid)
    {
        p_action->session_type = CTC_DTEL_INT_SESSION_TYPE_NONE;

    }
    else if (session_type == 7)
    {
        p_action->session_type = CTC_DTEL_INT_SESSION_TYPE_CANCEL;
    }
    else if (session_type == 4)
    {
        p_action->session_type = CTC_DTEL_INT_SESSION_TYPE_SINK;
        p_action->session_id = GetDsIntHeaderCamAction(V, intSessionId_f, &cam_action);
    }
        exception_en = GetDsIntHeaderCamAction(V, exceptionEn_f, &cam_action);
        discard = GetDsIntHeaderCamAction(V, discard_f, &cam_action);
        if (!exception_en && discard)
        {
            p_action->to_cpu = CTC_EXCP_DISCARD;
        }
        else if (!exception_en && !discard)
        {
            p_action->to_cpu = CTC_EXCP_NORMAL_FWD;
        }
        else if (exception_en && discard)
        {
            p_action->to_cpu = CTC_EXCP_DISCARD_AND_TO_CPU;
        }
        else
        {
            p_action->to_cpu = CTC_EXCP_FWD_AND_TO_CPU;
        }
    return CTC_E_NONE;

}

STATIC int32
_sys_usw_dtel_gen_rep(uint8 lchip, sys_dtel_pkt_t* p_int_pkt, sys_int_rep_param_t* rep_param)
{
    int32  ret = CTC_E_NONE;
    uint8  session_id = p_int_pkt->session_id;
    uint32 nh_id = 0;
    uint8  index = 0;
    uint8  md_cnt = 0;
    uint8  loop = 0;
    uint16 int_rep_hdr_len = 0;
    uint16 new_pkt_len = 0;
    uint8*  pkt_data = NULL;
    uint32 hw_int_rep_hdr[SYS_DTEL_MAX_INT_REP_HDR_LEN] = {0};
    sys_int_pkt_info_t* p_int_info = &(p_int_pkt->int_pkt_info);
    uint32 metadata[SYS_DTEL_REP_MD_BIT_NUM] = {0};
    sys_int_rep_hdr_t int_rep_hdr;
    ctc_pkt_tx_t *pkt_tx = NULL;

    metadata[0] = (p_int_info->local_src_port << 16) | p_int_info->local_dst_port;
    metadata[1] = (p_int_info->hop_lantency);
    metadata[2] = (p_int_info->queue_id << 24) | p_int_info->queue_cnt;
    metadata[3] = (p_int_info->igs_timestamp + p_int_info->hop_lantency);
    metadata[4] = (p_int_info->queue_id << 24);
    metadata[5] = (p_int_info->egs_port_load);

    sal_memset(&int_rep_hdr, 0, sizeof(sys_int_rep_hdr_t));
    int_rep_hdr.ver = 1;
    int_rep_hdr.rep_md_bits = rep_param->rep_md_bits[session_id];
    int_rep_hdr.f = p_int_pkt->int_pkt_info.is_postcard ? 0: 1;
    int_rep_hdr.hw_id = p_usw_dtel_master[lchip]->chip_id;
    int_rep_hdr.switch_id = p_usw_dtel_master[lchip]->switch_id;
    int_rep_hdr.sequence_number = p_usw_dtel_master[lchip]->rep_id++;
    nh_id = rep_param->nhid[session_id];

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DTEL, SYS_WB_APPID_DTEL_SUBID_MASTER, 1);

    int_rep_hdr.ingress_timestamp = p_int_info->igs_timestamp;
    for (index=SYS_DTEL_REP_MD_BIT_LOCAL_PORT; index<SYS_DTEL_REP_MD_BIT_NUM; index++)
    {
        if (CTC_IS_BIT_SET(int_rep_hdr.rep_md_bits, index))
        {
            int_rep_hdr.metadata[md_cnt++] = metadata[index];
        }
    }
    int_rep_hdr.length = 4 + md_cnt;
    int_rep_hdr_len = int_rep_hdr.length * sizeof(uint32);
    new_pkt_len = p_int_pkt->pkt_buf.len + int_rep_hdr_len;
    for (loop=0; loop<int_rep_hdr.length; loop++)
    {
        hw_int_rep_hdr[loop] = sal_htonl(((uint32*)(&int_rep_hdr))[loop]);
    }
    pkt_data  = p_int_pkt->pkt_buf.data + (MAX_GEN_PKT_PRE_LEN - int_rep_hdr_len);
    sal_memcpy(pkt_data, hw_int_rep_hdr, int_rep_hdr_len);

    if (!nh_id)
    {
        ctc_pkt_buf_t pkt_buf = {
                .data = pkt_data,
                .len  = new_pkt_len };
        p_int_pkt->pkt_rx.pkt_len = new_pkt_len - SYS_USW_DTEL_CRC_LEN; /*delete raw CRC (4B)*/
        p_int_pkt->pkt_rx.pkt_buf = &pkt_buf;
        p_int_pkt->pkt_rx.buf_count = 1;
        p_int_pkt->pkt_rx.rx_info.session_id = session_id;
        p_int_pkt->pkt_rx.rx_info.ptp.ts.seconds = p_int_info->igs_timestamp / 31250000ULL;
        p_int_pkt->pkt_rx.rx_info.ptp.ts.nanoseconds = p_int_info->igs_timestamp % 31250000ULL;
        p_int_pkt->pkt_rx.rx_info.ptp.egs_ts.seconds = metadata[SYS_DTEL_REP_MD_BIT_EGS_TIMESTAMP] / 31250000ULL;
        p_int_pkt->pkt_rx.rx_info.ptp.egs_ts.nanoseconds = metadata[SYS_DTEL_REP_MD_BIT_EGS_TIMESTAMP]% 31250000ULL;
        CTC_ERROR_RETURN(sys_usw_packet_usr_rx_cb(lchip, &p_int_pkt->pkt_rx));
        mem_free(p_int_pkt->pkt_buf.data);
    }
    else
    {
        sys_nh_info_dsnh_t nhinfo;
        sal_memset(&nhinfo, 0, sizeof(sys_nh_info_dsnh_t));
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, nh_id, &nhinfo, 0));

        MALLOC_ZERO(MEM_DTEL_MODULE, pkt_tx, sizeof(ctc_pkt_tx_t));
        CTC_ERROR_RETURN(NULL == pkt_tx ? CTC_E_NO_MEMORY: CTC_E_NONE);

        pkt_tx->tx_info.ttl = 64;
        pkt_tx->tx_info.nhid = nh_id;
        pkt_tx->tx_info.packet_type = CTC_PARSER_PKT_TYPE_RESERVED;
        CTC_SET_FLAG(pkt_tx->tx_info.flags, CTC_PKT_FLAG_NHID_VALID);
        pkt_tx->mode = p_int_pkt->pkt_rx.mode;
        pkt_tx->lchip = lchip;
        if (!nhinfo.is_mcast)
        {
            pkt_tx->tx_info.dest_gport = nhinfo.gport;
        }
        else
        {
            CTC_SET_FLAG(pkt_tx->tx_info.flags, CTC_PKT_FLAG_MCAST);
            pkt_tx->tx_info.dest_group_id = nhinfo.gport;
        }
        pkt_tx->skb.data = pkt_data;
        pkt_tx->skb.len = new_pkt_len- SYS_USW_DTEL_CRC_LEN; /*delete raw CRC (4B)*/
        ret = sys_usw_packet_tx(lchip, pkt_tx);
        mem_free(p_int_pkt->pkt_buf.data);
        mem_free(pkt_tx);
    }
    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "[INT Report] NH:%u  TxMode:%u md_cnt:%d\n" \
                                                                              "IntReportHdr:\n" \
                                                                              "0x%.8x\n" \
                                                                              "0x%.8x\n" \
                                                                              "0x%.8x\n" \
                                                                              "0x%.8x\n" \
                                                                              "0x%.8x\n" \
                                                                              "0x%.8x\n" \
                                                                              "0x%.8x\n" \
                                                                              "0x%.8x\n" \
                                                                              "0x%.8x\n" \
                                                                              "0x%.8x\n",
                                                                        p_usw_dtel_master[lchip]->nhid[session_id],
                                                                        p_int_pkt->pkt_rx.mode,
                                                                        md_cnt,
                                                                        ((uint32*)&int_rep_hdr)[0],
                                                                        ((uint32*)&int_rep_hdr)[1],
                                                                        ((uint32*)&int_rep_hdr)[2],
                                                                        ((uint32*)&int_rep_hdr)[3],
                                                                        ((uint32*)&int_rep_hdr)[4],
                                                                        ((uint32*)&int_rep_hdr)[5],
                                                                        ((uint32*)&int_rep_hdr)[6],
                                                                        ((uint32*)&int_rep_hdr)[7],
                                                                        ((uint32*)&int_rep_hdr)[8],
                                                                        ((uint32*)&int_rep_hdr)[9]);

    return ret;
}

STATIC int32
_sys_usw_dtel_rep_hash_traverse(void* bucket_data, void* user_data)
{
    sys_int_rep_param_t* rep_param = (sys_int_rep_param_t*)user_data;
    uint8  lchip = rep_param->lchip;
    sys_dtel_pkt_t* p_int_pkt = (sys_dtel_pkt_t*)bucket_data;

    if (NULL == p_int_pkt)
    {
        return CTC_E_NONE;
    }
    if (SYS_DTEL_REP_MODE_DONE == p_int_pkt->mode)
    {
        _sys_usw_dtel_gen_rep(lchip, p_int_pkt, rep_param);
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "  %%Dtel: INT rep done!\n");
        mem_free(p_int_pkt);
        return 1; //remove the node in hash.
    }
    else
    {
        uint32 delay = 0;   /*in ms*/
        sal_systime_t cur_ts;
        /*INT report aging*/
        sal_gettime(&cur_ts);
        if (cur_ts.tv_sec >= p_int_pkt->last_ts)
        {
            delay = cur_ts.tv_sec - p_int_pkt->last_ts;
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "  %%Dtel: delay: %ds!\n", delay);
        }
        if (delay > p_usw_dtel_master[lchip]->timeout)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "  %%Dtel: INT rep aging!\n");
            mem_free(p_int_pkt->pkt_buf.data);
            mem_free(p_int_pkt);
            return 1; //remove the node in hash.
        }
    }
    return CTC_E_NONE;
}

STATIC void
_sys_usw_dtel_rep_task(void* param)
{
    int32  ret = 0;
    sys_int_rep_param_t rep_param;
    uint8  lchip = (uintptr)param;

    rep_param.lchip = lchip;
    while(1)
    {
        ret = sal_sem_take(p_usw_dtel_master[lchip]->sink_sem, SAL_SEM_FOREVER);
        if (0 != ret)
        {
            continue;
        }
        SYS_LCHIP_CHECK_ACTIVE_IN_THREAD(lchip);
        SYS_CHIP_CHECK_RESET_HW_IN_THREAD(lchip);
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "  %%Dtel: INT rep task processing!\n");

        SYS_DTEL_LOCK(lchip);
        sal_memcpy(rep_param.nhid, p_usw_dtel_master[lchip]->nhid, CTC_DTEL_INT_SINK_SESSION_NUM * sizeof(uint32));
        sal_memcpy(rep_param.rep_md_bits, p_usw_dtel_master[lchip]->rep_md_bits, CTC_DTEL_INT_SINK_SESSION_NUM * sizeof(uint8));
        SYS_DTEL_UNLOCK(lchip);

        SYS_DTEL_SINK_LOCK(lchip);
        ctc_hash_traverse_remove(p_usw_dtel_master[lchip]->int_rep_info, \
                               (hash_traversal_fn)_sys_usw_dtel_rep_hash_traverse, &rep_param);
        SYS_DTEL_SINK_UNLOCK(lchip);
    }
}

STATIC uint32
_sys_usw_dtel_rep_hash_make(sys_dtel_pkt_t* p_rep)
{
    uint32 size = 0;
    uint8* k = NULL;

    CTC_PTR_VALID_CHECK(p_rep);
    size = CTC_OFFSET_OF(sys_dtel_pkt_t, calc_key_len);
    k = (uint8*)p_rep;
    return ctc_hash_caculate(size, k);
}

STATIC bool
_sys_usw_dtel_rep_hash_compare(sys_dtel_pkt_t* p_rep0,
                                           sys_dtel_pkt_t* p_rep1)
{
    uint32 size = 0;

    if (!p_rep0 || !p_rep1)
    {
        return FALSE;
    }
    size = CTC_OFFSET_OF(sys_dtel_pkt_t, calc_key_len);
    if (!sal_memcmp(p_rep0, p_rep1, size))
    {
        return TRUE;
    }
    return FALSE;
}

STATIC int32
_sys_usw_dtel_rep_hash_free_node(void* node_data, void* user_data)
{
    sys_dtel_pkt_t* p_pkt = NULL;

    if (node_data)
    {
        p_pkt = (sys_dtel_pkt_t*)node_data;
        mem_free(p_pkt->pkt_buf.data);
        mem_free(p_pkt);
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_mapping_metadata_idx(uint8 lchip,uint16 ins_bit, uint8 *metadata_idx,uint8 *len)
{
    switch(ins_bit)
    {
    case CTC_DTEL_INT_INS_SW_ID:
        metadata_idx[0] = 10;
        *len = 1;
        break;
    case CTC_DTEL_INT_INS_LV1_PORT:
        metadata_idx[0] = 8;
        *len = 1;
        break;
    case CTC_DTEL_INT_INS_HOP_LATENCY:
        metadata_idx[0] = 9;
        *len = 1;
        break;
    case CTC_DTEL_INT_INS_QUEUE_INFO:
        metadata_idx[0] = 6;
        *len = 1;
        break;
    case CTC_DTEL_INT_INS_IGS_TS:
        metadata_idx[0] = 2;
        *len = 1;
        break;
    case CTC_DTEL_INT_INS_EGS_TS:
        metadata_idx[0] = 3;
        *len = 1;
        break;
    case CTC_DTEL_INT_INS_LV2_PORT:
        metadata_idx[0] = 4;
        metadata_idx[1] = 5;
        *len = 2;
        break;
    case CTC_DTEL_INT_INS_EPTU:
        metadata_idx[0] = 7;
        *len = 1;
        break;
    default :
        metadata_idx[0] = 0;
        metadata_idx[1] = 0;
        *len = 0;
        break;

    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_ifa_mapping_metadata_idx(uint8 lchip, uint16 ins_bit, uint8 *metadata_idx, uint8 *len)
{
    if(SYS_DTEL_IFA_REQ_VEC_SW_ID == ins_bit)
    {
        metadata_idx[0] = 10;
        *len = 1;
        return CTC_E_NONE;
    }
    switch(ins_bit>>1)
    {
    case CTC_DTEL_IFA_REQ_VEC_LV1_PORT:
        metadata_idx[0] = 8;
        *len = 1;
        break;
    case CTC_DTEL_IFA_REQ_VEC_HOP_LATENCY:
        metadata_idx[0] = 9;
        *len = 1;
        break;
    case CTC_DTEL_IFA_REQ_VEC_QUEUE_INFO:
        metadata_idx[0] = 6;
        *len = 1;
        break;
    case CTC_DTEL_IFA_REQ_VEC_IGS_TS:
        metadata_idx[0] = 2;
        *len = 1;
        break;
    case CTC_DTEL_IFA_REQ_VEC_EGS_TS:
        metadata_idx[0] = 3;
        *len = 1;
        break;
    case CTC_DTEL_IFA_REQ_VEC_LV2_PORT:
        metadata_idx[0] = 4;
        metadata_idx[1] = 5;
        *len = 2;
        break;
    case CTC_DTEL_IFA_REQ_VEC_EPTU:
        metadata_idx[0] = 7;
        *len = 1;
        break;
    default:
        metadata_idx[0] = 0;
        metadata_idx[1] = 0;
        *len = 0;
        break;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_ifa_get_metadata_idx_mapping(uint8 lchip, uint8 index, uint8* ins_bit, uint8* len)
{
    switch(index)
    {
    case 9:
        *ins_bit = CTC_DTEL_IFA_REQ_VEC_HOP_LATENCY;
        *len = 1;
        break;
    case 8:
        *ins_bit = CTC_DTEL_IFA_REQ_VEC_LV1_PORT;
        *len = 1;
        break;
    case 7:
        *ins_bit = CTC_DTEL_IFA_REQ_VEC_EPTU;
        *len = 1;
        break;
    case 6:
        *ins_bit = CTC_DTEL_IFA_REQ_VEC_QUEUE_INFO;
        *len = 1;
        break;
    case 5:
    case 4:
        *ins_bit = CTC_DTEL_IFA_REQ_VEC_LV2_PORT;
        *len = 2;
        break;
    case 3:
        *ins_bit = CTC_DTEL_IFA_REQ_VEC_EGS_TS;
        *len = 1;
        break;
    case 2:
        *ins_bit = CTC_DTEL_IFA_REQ_VEC_IGS_TS;
        *len = 1;
        break;
    default:
        *ins_bit = 0x00;
        *len = 0;
        break;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_set_int_cfg(uint8 lchip, ctc_dtel_int_cfg_t *p_cfg)
{
    uint32 threshold = 0;
    DsIntIgrSinkSession_m igr_session;
    DsIntEgrSinkSession_m egr_session;
    sys_dtel_pkt_t int_pkt;
    sys_nh_info_dsnh_t nhinfo;
    uint32 cmd = 0;
    uint8   igs_log_en = 0;
    uint8   egs_log_en = 0;
    uint8  igs_random_en = 0;
    uint8  egs_random_en = 0;
    uint8   follow_igs_log = 0;
    uint8   old_log_id = 0;
    uint8 bits_set_all = 0;
    uint32 tmp[SYS_DTEL_INT_SEN_BMP_LEN] = {0};

    CTC_MAX_VALUE_CHECK(p_cfg->log_id, SYS_DTEL_INT_LOG_ID_NUM - 1);
    CTC_MAX_VALUE_CHECK(p_cfg->log_percent, CTC_LOG_PERCENT_MAX - 1);
    bits_set_all = CTC_DTEL_INT_REP_LV1_PORT | CTC_DTEL_INT_REP_HOP_LATENCY \
                 | CTC_DTEL_INT_REP_QUEUE_INFO | CTC_DTEL_INT_REP_EGR_TS | CTC_DTEL_INT_REP_EPTU;/* 0x2F */
    if(p_cfg->rep_md_bits & (~bits_set_all))
    {
        return CTC_E_INVALID_PARAM;
    }

    sal_memset(&egr_session, 0, sizeof(DsIntEgrSinkSession_m));
    sal_memset(&int_pkt, 0, sizeof(sys_dtel_pkt_t));
    sal_memset(&nhinfo, 0, sizeof(sys_nh_info_dsnh_t));
    if (p_usw_dtel_master[lchip]->ifa_en)
    {
        CTC_ERROR_RETURN(CTC_E_INVALID_CONFIG);
    }

    igs_log_en = p_cfg->log_en && !p_cfg->postcard_en? 1: 0;
    egs_log_en = p_cfg->log_en;
    igs_random_en = igs_log_en && p_cfg->log_percent;
    egs_random_en = egs_log_en && p_cfg->log_percent;
    follow_igs_log = igs_log_en || igs_random_en;

    _sys_dtel_mapping_log_percent(lchip, p_cfg->log_percent, &threshold);
    if (p_cfg->nh_id)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_cfg->nh_id, &nhinfo, 0));
    }

    if (p_cfg->log_en
       && ((CTC_IS_BIT_SET(p_usw_dtel_master[lchip]->postcard_en, p_cfg->log_id) && !p_cfg->postcard_en)
      || (CTC_IS_BIT_SET(p_usw_dtel_master[lchip]->inband_en, p_cfg->log_id) && p_cfg->postcard_en)))
    {
        /* Check logId only used for inband or poscard */
        CTC_BMP_SET(tmp, p_cfg->session_id);
        if (CTC_BMP_ISSET(p_usw_dtel_master[lchip]->log_en[p_cfg->log_id], p_cfg->session_id)
           && !sal_memcmp(p_usw_dtel_master[lchip]->log_en[p_cfg->log_id], tmp, sizeof(tmp)))
        {
            /* if the logId only used for one session, that can be changed */
        }
        else
        {
            CTC_ERROR_RETURN(CTC_E_INVALID_CONFIG);
        }
    }

    cmd = DRV_IOR(DsIntIgrSinkSession_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &igr_session));
    old_log_id = GetDsIntIgrSinkSession(V, logId_f, &igr_session);
    sal_memset(&igr_session, 0, sizeof(DsIntIgrSinkSession_m));

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DTEL, SYS_WB_APPID_DTEL_SUBID_MASTER, 1);
    if (p_cfg->log_en)
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "igs_log_en:%u\n", igs_log_en);
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "egs_log_en:%u\n", egs_log_en);
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "follow_igs_log:%u\n", follow_igs_log);
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "log_id:%u\n", p_cfg->log_id);

        SetDsIntIgrSinkSession(V, logEn_f, &igr_session, igs_random_en ? 0 : igs_log_en);
        SetDsIntIgrSinkSession(V, logId_f, &igr_session, p_cfg->log_id);
        SetDsIntIgrSinkSession(V, logBlock_f, &igr_session, 9);    // ACL log 7
        SetDsIntIgrSinkSession(V, randomEn_f, &igr_session, igs_random_en);
        SetDsIntIgrSinkSession(V, randomThreshold_f, &igr_session, threshold);
        SetDsIntIgrSinkSession(V, egrSinkSessionId_f, &igr_session, p_cfg->session_id);

        SetDsIntEgrSinkSession(V, logEn_f, &egr_session, (egs_random_en || follow_igs_log) ? 0 : egs_log_en);
        SetDsIntEgrSinkSession(V, logFollowIgr_f, &egr_session, follow_igs_log);
        SetDsIntEgrSinkSession(V, logId_f, &egr_session, p_cfg->log_id);
        SetDsIntEgrSinkSession(V, logBlock_f, &egr_session, 7);    // ACL log 2
        SetDsIntEgrSinkSession(V, randomEn_f, &egr_session,  follow_igs_log ? 0 : egs_random_en);
        SetDsIntEgrSinkSession(V, randomThreshold_f, &egr_session, threshold);
    }
    cmd = DRV_IOW(DsIntIgrSinkSession_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &igr_session));
    cmd = DRV_IOW(DsIntEgrSinkSession_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &egr_session));

    if (CTC_BMP_ISSET(p_usw_dtel_master[lchip]->log_en[old_log_id], p_cfg->session_id))
    {
        sal_memset(tmp, 0, sizeof(tmp));
        /*update old logid*/
        CTC_BMP_UNSET(p_usw_dtel_master[lchip]->log_en[old_log_id], p_cfg->session_id);
        if (!sal_memcmp(p_usw_dtel_master[lchip]->log_en[old_log_id], tmp, sizeof(tmp)))
        {
            CTC_BIT_UNSET(p_usw_dtel_master[lchip]->postcard_en, old_log_id);
            CTC_BIT_UNSET(p_usw_dtel_master[lchip]->inband_en, old_log_id);
        }
    }

    if (p_cfg->log_en)
    {
        CTC_BMP_SET(p_usw_dtel_master[lchip]->log_en[p_cfg->log_id], p_cfg->session_id);
        if (p_cfg->postcard_en)
        {
            CTC_BIT_SET(p_usw_dtel_master[lchip]->postcard_en, p_cfg->log_id);
        }
        else
        {
            CTC_BIT_SET(p_usw_dtel_master[lchip]->inband_en, p_cfg->log_id);
        }
    }
    p_usw_dtel_master[lchip]->nhid[p_cfg->session_id] = p_cfg->log_en ? p_cfg->nh_id: 0;
    p_usw_dtel_master[lchip]->rep_md_bits[p_cfg->session_id] = p_cfg->log_en ? p_cfg->rep_md_bits : 0;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_get_int_cfg(uint8 lchip, ctc_dtel_int_cfg_t *p_cfg)
{
    uint32 threshold = 0;
    DsIntIgrSinkSession_m  igr_session;
    DsIntEgrSinkSession_m egr_session;
    uint32 cmd = 0;
    /*uint8   igs_log_en = 0;
    uint8   egs_log_en = 0;*/
    uint8   log_id = 0;


    sal_memset(&igr_session, 0, sizeof(DsIntIgrSinkSession_m));
    sal_memset(&egr_session, 0, sizeof(DsIntEgrSinkSession_m));

    cmd = DRV_IOR(DsIntIgrSinkSession_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &igr_session));
    /*igs_log_en = GetDsIntIgrSinkSession(V, logEn_f, &igr_session);*/
    threshold = GetDsIntIgrSinkSession(V, randomThreshold_f, &igr_session);
    cmd = DRV_IOR(DsIntEgrSinkSession_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &egr_session));
    /*egs_log_en = GetDsIntEgrSinkSession(V, logEn_f, &egr_session);*/
    log_id = GetDsIntEgrSinkSession(V, logId_f, &egr_session);
    p_cfg->log_id = log_id;
    _sys_dtel_unmapping_log_percent(lchip, threshold, &p_cfg->log_percent);

    p_cfg->postcard_en = CTC_IS_BIT_SET(p_usw_dtel_master[lchip]->postcard_en, log_id);
    p_cfg->log_en = CTC_BMP_ISSET(p_usw_dtel_master[lchip]->log_en[log_id], p_cfg->session_id) ? 1 : 0;
    p_cfg->nh_id = p_usw_dtel_master[lchip]->nhid[p_cfg->session_id];
    p_cfg->rep_md_bits = p_usw_dtel_master[lchip]->rep_md_bits[p_cfg->session_id];
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_int_check_set_mode_param(ctc_dtel_int_mode_cfg_t p_mode_cfg)
{
    uint32 tmp_bitmap = 0;
    int32 bit_count = 0;

    CTC_MAX_VALUE_CHECK(p_mode_cfg.l4_chksum_mode, 2);

    if ((p_mode_cfg.dscp & 0x8000) == 0)
    {
        /* The 15 bit is not set, the value of dscp is depended on 1 bit of the lower 6 bits */
        if(p_mode_cfg.dscp >> 6 != 0)
        {
            return CTC_E_INVALID_PARAM;
        }
        CTC_BMP_COUNT((tmp_bitmap | p_mode_cfg.dscp), bit_count, 0, 5);
        if (bit_count > 1)
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    else
    {
        /* The 15 bit is set, the value of dscp is depended on lower 6 bits */
        p_mode_cfg.dscp &= 0x7FFF;
        if (p_mode_cfg.dscp >> 6 != 0)
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_int_set_mode_cfg(uint8 lchip, ctc_dtel_int_mode_cfg_t* p_mode_cfg)
{
    ParserLayer4AppCtl_m parser_int;
    DsIntEditCtl_m epe_edit;
    EpeHeaderEditCtl_m epe_hdr_edit_ctl;
    DsIntExtRewriteProfile_m  flex_edit;
    uint32 cmd = 0;
    uint8 probe_marker_valid = 0;
    uint8 l4_chksum_mode = 0;
    uint8 flex_edit_idx = 0;
    uint8 loop = 0;
    uint8 encap_mode = 0;
    uint8 is_ipv6 = 0, is_tcp = 0;
    uint8 l4checksumsel = 0;
    uint8 set_zero = 0;
    uint8 l4ChksumUpdate = 0;
    uint8 l4ChksumUpdateX = 0;

    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "int-mode:%u, probe-marker:0x%08x%08x, l4-dst-port:%u, dscp:%u\n",
                                            p_mode_cfg->mode, p_mode_cfg->probe_marker[1], p_mode_cfg->probe_marker[0], p_mode_cfg->l4_dest_port, p_mode_cfg->dscp);
    CTC_MAX_VALUE_CHECK(p_mode_cfg->mode, CTC_DTEL_INT_MODE_MAX - 1);

    CTC_ERROR_RETURN(_sys_usw_dtel_int_check_set_mode_param(*p_mode_cfg));
    p_usw_dtel_master[lchip]->dscp = p_mode_cfg->dscp;
    l4_chksum_mode = p_mode_cfg->l4_chksum_mode;
    
    probe_marker_valid = p_mode_cfg->probe_marker[0] || p_mode_cfg->probe_marker[1];
    cmd = DRV_IOR(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_edit_ctl));
    if (GetEpeHeaderEditCtl(V, intEn_f, &epe_hdr_edit_ctl))
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Do not support modify mode config when INT already enabled.\n");
        return CTC_E_IN_USE;
    }
    cmd = DRV_IOR(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));
    cmd = DRV_IOR(DsIntEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));

    if (CTC_DTEL_INT_MODE_PROBE_MARKER == p_mode_cfg->mode)
    {   /*dscp mode init @ _sys_usw_dtel_init_parser*/
        SetParserLayer4AppCtl(V, udpIntProbeMarkDis_f, &parser_int, probe_marker_valid ? 0 : 1);
        SetParserLayer4AppCtl(A, udpIntProbeMark_f, &parser_int, p_mode_cfg->probe_marker);
        SetParserLayer4AppCtl(V, udpIntDestPortDis_f, &parser_int, p_mode_cfg->l4_dest_port ? 0 : 1);
        SetParserLayer4AppCtl(V, udpIntDestPort_f, &parser_int, p_mode_cfg->l4_dest_port);
        SetParserLayer4AppCtl(V, tcpIntProbeMarkDis_f, &parser_int, probe_marker_valid ? 0 : 1);
        SetParserLayer4AppCtl(A, tcpIntProbeMark_f, &parser_int, p_mode_cfg->probe_marker);
        SetParserLayer4AppCtl(V, tcpIntDestPortDis_f, &parser_int, p_mode_cfg->l4_dest_port ? 0 : 1);
        SetParserLayer4AppCtl(V, tcpIntDestPort_f, &parser_int, p_mode_cfg->l4_dest_port);
    }
    SetDsIntEditCtl(V, probeMaker0_f, &epe_edit, (CTC_DTEL_INT_MODE_PROBE_MARKER == p_mode_cfg->mode) ? p_mode_cfg->probe_marker[1] : 0);
    SetDsIntEditCtl(V, probeMaker1_f, &epe_edit, (CTC_DTEL_INT_MODE_PROBE_MARKER == p_mode_cfg->mode) ? p_mode_cfg->probe_marker[0] : 0);
    SetParserLayer4AppCtl(V, udpProbeIntEn_f, &parser_int, (CTC_DTEL_INT_MODE_PROBE_MARKER == p_mode_cfg->mode) ? 1 : 0);
    SetParserLayer4AppCtl(V, tcpProbeIntEn_f, &parser_int, (CTC_DTEL_INT_MODE_PROBE_MARKER == p_mode_cfg->mode) ? 1 : 0);
    SetParserLayer4AppCtl(V, intParserAdjLen_f, &parser_int, (CTC_DTEL_INT_MODE_PROBE_MARKER == p_mode_cfg->mode) ? 8 : 0);
    cmd = DRV_IOW(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));
    cmd = DRV_IOW(DsIntEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));

    if (2 == l4_chksum_mode)/* Update l4 checksum */
    {
        l4checksumsel = 0;
        set_zero = 0;
        l4ChksumUpdate = 1;
        l4ChksumUpdateX = 1;
    }
    else if (1 == l4_chksum_mode) /* Do not update l4 checksum */
    {
        l4checksumsel = 0x10;
        l4ChksumUpdate = 0;
        l4ChksumUpdateX = 0;
    }
    else /* To set l4 checksum to 0 */
    {
        l4checksumsel = 0;
        set_zero = 1;
        l4ChksumUpdate = 1;
        l4ChksumUpdateX = 1;
    }
    for (loop = 0; loop < ((SYS_INT_EDITMODE_SINK_TCPRAW + 1) << 1); loop++)
    {
        encap_mode = (loop >> 1) & 3;/* Encap mode : 00-UDPPROBE;01-TCPPROBE; 10- UDPRAW;11-TCPRAW */
        is_ipv6 = loop & 0x1;
        is_tcp = encap_mode & 0x1;
        flex_edit_idx = ((loop & 0xF8) >> 1) | (is_ipv6 ? 0x0 : 0x1) | (is_tcp ? 0x0 : 0x2);

        cmd = DRV_IOR(DsIntExtRewriteProfile_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, flex_edit_idx, cmd, &flex_edit));
        SetDsIntExtRewriteProfile(V, l4ChecksumSel_f, &flex_edit, l4checksumsel);
        SetDsIntExtRewriteProfile(V, intForceL4ChecksumEqualZero_f, &flex_edit, set_zero);
        SetDsIntExtRewriteProfile(V, l4ChksumUpdate_f, &flex_edit, l4ChksumUpdate);
        SetDsIntExtRewriteProfile(V, l4ChksumUpdateX_f, &flex_edit, l4ChksumUpdateX);
        cmd = DRV_IOW(DsIntExtRewriteProfile_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, flex_edit_idx, cmd, &flex_edit));
    }
    
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_int_get_mode_cfg(uint8 lchip, ctc_dtel_int_mode_cfg_t* p_mode_cfg)
{
    ParserLayer4AppCtl_m parser_int;
    DsIntExtRewriteProfile_m  flex_edit;
    uint32 cmd = 0;
    uint8 probe_marker_mode = 0;
    uint8 set_zero = 0;
    uint8 l4checksumsel = 0;
    uint8 l4ChksumUpdate = 0;
    uint8 l4ChksumUpdateX = 0;

    cmd = DRV_IOR(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));
    probe_marker_mode = GetParserLayer4AppCtl(V, udpProbeIntEn_f, &parser_int);
    p_mode_cfg->mode = probe_marker_mode ? CTC_DTEL_INT_MODE_PROBE_MARKER : CTC_DTEL_INT_MODE_DSCP;
    if (probe_marker_mode)
    {
        GetParserLayer4AppCtl(A, udpIntProbeMark_f, &parser_int, p_mode_cfg->probe_marker);
        p_mode_cfg->l4_dest_port = GetParserLayer4AppCtl(V, udpIntDestPort_f, &parser_int);
    }
    else
    {
        p_mode_cfg->dscp = p_usw_dtel_master[lchip]->dscp;
    }

    cmd = DRV_IOR(DsIntExtRewriteProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &flex_edit));
    l4checksumsel = GetDsIntExtRewriteProfile(V, l4ChecksumSel_f, &flex_edit);
    set_zero = GetDsIntExtRewriteProfile(V, intForceL4ChecksumEqualZero_f, &flex_edit);
    l4ChksumUpdate = GetDsIntExtRewriteProfile(V, l4ChksumUpdate_f, &flex_edit);
    l4ChksumUpdateX = GetDsIntExtRewriteProfile(V, l4ChksumUpdateX_f, &flex_edit);
    if (!(l4checksumsel & 0x10) && (!set_zero) && l4ChksumUpdate && l4ChksumUpdateX)
    {
        p_mode_cfg->l4_chksum_mode = 2; /* Update l4 checksum */
    }
    else if ((l4checksumsel & 0x10) && !l4ChksumUpdate && !l4ChksumUpdateX)
    {
        p_mode_cfg->l4_chksum_mode = 1; /* Do not update l4 checksum */
    }
    else
    {
        p_mode_cfg->l4_chksum_mode = 0; /* To set l4 checksum to 0 */
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_init_parser(uint8 lchip, uint8 enable)
{
    ParserLayer4AppCtl_m parser_int;
    EpePktProcCtl_m epe_pkt_proc;
    ParserIpCtl_m parser_ip;
    ds_t ds;
    uint32 cmd = 0, field_val =0;
    uint8 probe_marker_mode = 0;
    uint16 dscp = 0;

    cmd = DRV_IOR(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));
    field_val = enable? 1 : 0;
    probe_marker_mode = GetParserLayer4AppCtl(V, udpProbeIntEn_f, &parser_int);
    SetParserLayer4AppCtl(V, intIpv4UdpProbeMarkEn_f, &parser_int, probe_marker_mode ? field_val : 0);
    SetParserLayer4AppCtl(V, intIpv6UdpProbeMarkEn_f, &parser_int, probe_marker_mode ? field_val : 0);
    SetParserLayer4AppCtl(V, intIpv4TcpProbeMarkEn_f, &parser_int, probe_marker_mode ? field_val : 0);
    SetParserLayer4AppCtl(V, intIpv6TcpProbeMarkEn_f, &parser_int, probe_marker_mode ? field_val : 0);
    SetParserLayer4AppCtl(V, intIpv4UdpTosMarkEn_f, &parser_int, probe_marker_mode ? 0 : field_val);
    SetParserLayer4AppCtl(V, intIpv6UdpTosMarkEn_f, &parser_int, probe_marker_mode ? 0 : field_val);
    SetParserLayer4AppCtl(V, intIpv4TcpTosMarkEn_f, &parser_int, probe_marker_mode ? 0 : field_val);
    SetParserLayer4AppCtl(V, intIpv6TcpTosMarkEn_f, &parser_int, probe_marker_mode ? 0 : field_val);
    field_val = enable? 0x0000ff00 : 0;
    SetParserLayer4AppCtl(V, intLenFiledMask_f, &parser_int, field_val);
    field_val = enable? 8 : 0;
    SetParserLayer4AppCtl(V, intLenFiledShift_f, &parser_int, field_val);
    field_val = enable? 64: 0;
    SetParserLayer4AppCtl(V, intParserMaxLen_f, &parser_int, field_val);
    cmd = DRV_IOW(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));

    dscp = p_usw_dtel_master[lchip]->dscp ? p_usw_dtel_master[lchip]->dscp : 4; /* The default value is 4 */
    cmd = DRV_IOR(ParserIpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_ip));
    field_val = enable ? ((dscp & 0x8000) ? 0x3F : (dscp & 0x3F)) : 0;
    SetParserIpCtl(V, intMarkTosMask_f, &parser_ip, probe_marker_mode ? 0 : field_val);
    field_val = enable ? (dscp & 0x3F) : 0;
    SetParserIpCtl(V, intMarkTos_f, &parser_ip, probe_marker_mode ? 0 : field_val);
    cmd = DRV_IOW(ParserIpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_ip));

    cmd = DRV_IOR(EpePktProcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_pkt_proc));
    field_val = enable ? ((dscp & 0x8000) ? 0x3F : (dscp & 0x3F)) : 0;
    SetEpePktProcCtl(V, intDscpMask_f, &epe_pkt_proc, probe_marker_mode ? 0 : field_val);
    field_val = enable ? (dscp & 0x3F) : 0;
    SetEpePktProcCtl(V, intDscpValue_f, &epe_pkt_proc, probe_marker_mode ? 0 : field_val);
    cmd = DRV_IOW(EpePktProcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_pkt_proc));

    field_val = enable? 1 : 0;
    cmd = DRV_IOW(EpeMiscLogCtl_t, EpeMiscLogCtl_logIdOverWriteMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    field_val = enable? 1 : 0;
    cmd = DRV_IOR(IpeSecondaryParserCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetIpeSecondaryParserCtl(V, tunnelDecapCon0_f, &ds, field_val);
    SetIpeSecondaryParserCtl(V, tunnelDecapAdjust_f, &ds, (probe_marker_mode && enable) ? 8 : 0);
    cmd = DRV_IOW(IpeSecondaryParserCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));

    cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetIpeFwdIntCtl(V, tunnelDecapCon0_f, &ds, field_val);
    SetIpeFwdIntCtl(V, tunnelDecapAdjust_f, &ds, (probe_marker_mode && enable) ? 8 : 0);
    cmd = DRV_IOW(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));

    CTC_ERROR_RETURN(sys_usw_parser_set_vxlan_int_l4_decode(lchip, probe_marker_mode));
    return CTC_E_NONE;

}

STATIC int32
_sys_usw_dtel_set_fwd_register(uint8 lchip, uint8 enable)
{
    uint32 cmd = 0;
    uint32 field_val = 0;
    IpeFwdIntCtl_m fwd_int;
    EpeMiscLogCtl_m epe_misc_log_ctl;
    EpeHeaderEditCtl_m epe_hdr_edit_ctl;

    field_val = enable ? 1: 0;
    cmd = DRV_IOW(EpeHdrAdjustCtl_t, EpeHdrAdjustCtl_keepPacketHeaderToRemoteCpuMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    field_val = enable ? 2 : 1;
    cmd = DRV_IOW(EpeHdrAdjustCtl_t, EpeHdrAdjustCtl_tempQMsgInfoType_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    cmd = DRV_IOW(QWriteCtl_t, QWriteCtl_tempQMsgInfoType_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    if((DRV_IS_TMM(lchip) && SYS_GET_CHIP_VERSION == SYS_CHIP_SUB_VERSION_A) || DRV_IS_TMG(lchip))
    {
        field_val = enable ? 1 : 0;
        cmd = DRV_IOW(IpeFwdCtl_t, IpeFwdCtl_glbIntOrSrOrIpfixMode_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

        field_val = enable ? 1 : 0;
        cmd = DRV_IOW(EpeHdrAdjustCtl_t, EpeHdrAdjustCtl_glbIntOrSrOrIpfixMode_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    }

    cmd = DRV_IOR(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_edit_ctl));
    SetEpeHeaderEditCtl(V, ttlIntSinkSessionId_f, &epe_hdr_edit_ctl, enable ? 1 : 0);
    SetEpeHeaderEditCtl(V, intEn_f, &epe_hdr_edit_ctl, enable ? 1 : 0);
    SetEpeHeaderEditCtl(V, intOverWrite_f, &epe_hdr_edit_ctl, enable ? 1 : 0);
    cmd = DRV_IOW(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_edit_ctl));

    field_val = enable ? 1 : 0;
    cmd = DRV_IOW(EpeNextHopCtl_t, EpeNextHopCtl_intEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    cmd = DRV_IOR(EpeMiscLogCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_misc_log_ctl));
    SetEpeMiscLogCtl(V, intOperationType_f, &epe_misc_log_ctl, enable ? 1 : 0);
    field_val = enable ? 0x81 : 0;
    SetEpeMiscLogCtl(V, intHeaderEnVector_f, &epe_misc_log_ctl, field_val);
    SetEpeMiscLogCtl(V, intHeaderEnVectorMask_f, &epe_misc_log_ctl, field_val);
    cmd = DRV_IOW(EpeMiscLogCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_misc_log_ctl));

    cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
    SetIpeFwdIntCtl(V, logIdOverWriteMode_f, &fwd_int, 0); /* if set, random disable */
    SetIpeFwdIntCtl(V, g_0_validMask_f, &fwd_int, enable ? 0xFF0003 : 0);
    SetIpeFwdIntCtl(V, g_1_validMask_f, &fwd_int, enable ? 0x007FE000 : 0);
    SetIpeFwdIntCtl(V, g_2_validMask_f, &fwd_int, enable ? 0x00FFFFFF : 0);
    SetIpeFwdIntCtl(V, intDefOpTypeTransit_f, &fwd_int, enable ? 2 : 0);
    SetIpeFwdIntCtl(V, intDefOpTypeSource_f, &fwd_int, 0);
    SetIpeFwdIntCtl(V, intDefOpPtrSource_f, &fwd_int, 0);
    SetIpeFwdIntCtl(V, intReportLenThreshold_f, &fwd_int, enable ? 0xFF : 0);
    SetIpeFwdIntCtl(V, intSinkLenThreshold_f, &fwd_int, enable ? 0xFF : 0);
    SetIpeFwdIntCtl(V, remainHopThreshold_f, &fwd_int, enable ? 1 : 0);
    cmd = DRV_IOW(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));

    field_val = 0;
    cmd = DRV_IOW(EpePktProcTsMiscCtl_t, EpePktProcTsMiscCtl_tsGranularity_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_init_fwd(uint8 lchip, uint8 enable)
{
    SYS_DTEL_INT_KEY_DEF;
    sys_int_cam_action_t action;
    ctc_dtel_int_cfg_t int_cfg;

#define SYS_INT_CAM_ENCAP_TYPE  (probe_marker_mode ? 0x2 : 0x1)  /*tcpraw/udpraw = b'01, tcpprob = b'10*/
#define SYS_INT_CAM_ENCAP_TYPE_MASK   (probe_marker_mode ? 0x2 : 0x1) /*tcpraw/udpraw = b'01, tcpprob = b'10*/
#define SYS_INT_CAM_ENCAP_TYPE_UDP_PROBE  0x4  /*udpprob = b'100*/
#define SYS_INT_CAM_ENCAP_TYPE_MASK_UDP_PROBE   0x4 /*udpprob = b'100*/

#define SYS_INT_POST_VER_FLAG(VAL) ((VAL) | (SYS_DTEL_INT_VER << 12))
#define SYS_INT_POST_VER_FLAG_MASK(MASK) ((MASK) | (SYS_DTEL_INT_VER_MASK << 12))
#define SYS_INT_CAM_SET_UDP_PROBE \
        if (probe_marker_mode) {\
            action.cam_idx += SYS_INT_HDRCAM_IDX_BASE_UDP_PROB; \
            SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE_UDP_PROBE, SYS_INT_CAM_ENCAP_TYPE_MASK_UDP_PROBE);\
            SYS_DTEL_INT_CAM_SET(lchip, action);\
        }

    if (enable)
    {
        ParserLayer4AppCtl_m parser_int;
        uint32 cmd = 0;
        uint8 probe_marker_mode = 0;

        cmd = DRV_IOR(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));
        probe_marker_mode = GetParserLayer4AppCtl(V, udpProbeIntEn_f, &parser_int);

        /*transmit mode: exceed intReportLenThreshold default to sink session */
        SYS_DTEL_INT_KEY_INIT;
        sal_memset(&action, 0, sizeof(action));
        action.cam_idx = SYS_INT_HDRCAM_IDX_EXCEED_REPORT_LEN;
        SYS_DTEL_INT_KEY_SET(zeroField0, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField1, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField2, 1, 1);
        SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE, SYS_INT_CAM_ENCAP_TYPE_MASK);
        SYS_DTEL_INT_KEY_SET(intType, CTC_PARSER_INT_TYPE_HOP_BY_HOP, 0xFF);
        SYS_DTEL_INT_KEY_SET(intVerFlag, SYS_INT_POST_VER_FLAG(0), SYS_INT_POST_VER_FLAG_MASK(0xE7F));
        SYS_DTEL_INT_KEY_SET(intLenThreshold0, 1, 1);
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_SINK;
        action.session_id = 31;
        action.to_cpu = CTC_EXCP_NORMAL_FWD;
        SYS_DTEL_INT_CAM_SET(lchip, action);
        SYS_INT_CAM_SET_UDP_PROBE;

        /*transmit mode: exceed intSinkLenThreshold default to sink session */
        SYS_DTEL_INT_KEY_INIT;
        sal_memset(&action, 0, sizeof(action));
        action.cam_idx = SYS_INT_HDRCAM_IDX_EXCEED_SINK_LEN;
        SYS_DTEL_INT_KEY_SET(zeroField0, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField1, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField2, 1, 1);
        SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE, SYS_INT_CAM_ENCAP_TYPE_MASK);
        SYS_DTEL_INT_KEY_SET(intType, CTC_PARSER_INT_TYPE_HOP_BY_HOP, 0xFF);
        SYS_DTEL_INT_KEY_SET(intVerFlag, SYS_INT_POST_VER_FLAG(0), SYS_INT_POST_VER_FLAG_MASK(0xE7F));
        SYS_DTEL_INT_KEY_SET(intLenThreshold1, 1, 1);
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_SINK;
        action.session_id = 31;
        action.to_cpu = CTC_EXCP_NORMAL_FWD;
        SYS_DTEL_INT_CAM_SET(lchip, action);
        SYS_INT_CAM_SET_UDP_PROBE;

        /*invalid E2E Pkt to CPU at sink node*/
        SYS_DTEL_INT_KEY_INIT;
        sal_memset(&action, 0, sizeof(action));
        action.cam_idx = SYS_INT_HDRCAM_IDX_E2E;
        SYS_DTEL_INT_KEY_SET(zeroField0, 1, 1);
        SYS_DTEL_INT_KEY_SET(intType, CTC_PARSER_INT_TYPE_DESTINATION, 0xFF);
        SYS_DTEL_INT_KEY_SET(intSessionType, 4, 7);
        SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE, SYS_INT_CAM_ENCAP_TYPE_MASK);
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_CANCEL;
        action.to_cpu = CTC_EXCP_DISCARD_AND_TO_CPU;
        SYS_DTEL_INT_CAM_SET(lchip, action);

        /*invalid E2E Pkt to CPU at transit node*/
        SYS_DTEL_INT_KEY_INIT;
        sal_memset(&action, 0, sizeof(action));
        action.cam_idx = SYS_INT_HDRCAM_IDX_E2E_TRANSIT;
        SYS_DTEL_INT_KEY_SET(zeroField0, 1, 1);
        SYS_DTEL_INT_KEY_SET(intType, CTC_PARSER_INT_TYPE_DESTINATION, 0xFF);
        SYS_DTEL_INT_KEY_SET(intSessionType, 0, 4);
        SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE, SYS_INT_CAM_ENCAP_TYPE_MASK);
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_CANCEL;
        action.to_cpu = CTC_EXCP_NORMAL_FWD;
        SYS_DTEL_INT_CAM_SET(lchip, action);

        /*invalid C,check and to cpu  */
        SYS_DTEL_INT_KEY_INIT;
        sal_memset(&action, 0, sizeof(action));
        action.cam_idx = SYS_INT_HDRCAM_IDX_CBIT_EQ_1;
        SYS_DTEL_INT_KEY_SET(zeroField0, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField1, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField2, 1, 1);
        SYS_DTEL_INT_KEY_SET(intType, CTC_PARSER_INT_TYPE_HOP_BY_HOP, 0xFF);
        SYS_DTEL_INT_KEY_SET(intVerFlag, SYS_INT_POST_VER_FLAG(0x200), SYS_INT_POST_VER_FLAG_MASK(0x27F));
        SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE, SYS_INT_CAM_ENCAP_TYPE_MASK);
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_CANCEL;
        action.to_cpu = CTC_EXCP_DISCARD_AND_TO_CPU;
        SYS_DTEL_INT_CAM_SET(lchip, action);
        SYS_INT_CAM_SET_UDP_PROBE;

        /*invalid REP =1/3 ,check and to cpu  */
        SYS_DTEL_INT_KEY_INIT;
        sal_memset(&action, 0, sizeof(action));
        action.cam_idx = SYS_INT_HDRCAM_IDX_REPBIT_EQ_1;
        SYS_DTEL_INT_KEY_SET(zeroField0, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField1, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField2, 1, 1);
        SYS_DTEL_INT_KEY_SET(intType, CTC_PARSER_INT_TYPE_HOP_BY_HOP, 0xFF);
        SYS_DTEL_INT_KEY_SET(intVerFlag, SYS_INT_POST_VER_FLAG(0x400), SYS_INT_POST_VER_FLAG_MASK(0x47F));
        SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE, SYS_INT_CAM_ENCAP_TYPE_MASK);
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_CANCEL;
        action.to_cpu = CTC_EXCP_DISCARD_AND_TO_CPU;
        SYS_DTEL_INT_CAM_SET(lchip, action);
        SYS_INT_CAM_SET_UDP_PROBE;

        /*invalid REP = 2/3 ,check and to cpu  */
        SYS_DTEL_INT_KEY_INIT;
        sal_memset(&action, 0, sizeof(action));
        action.cam_idx = SYS_INT_HDRCAM_IDX_REPBIT_EQ_2;
        SYS_DTEL_INT_KEY_SET(zeroField0, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField1, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField2, 1, 1);
        SYS_DTEL_INT_KEY_SET(intType, CTC_PARSER_INT_TYPE_HOP_BY_HOP, 0xFF);
        SYS_DTEL_INT_KEY_SET(intVerFlag, SYS_INT_POST_VER_FLAG(0x800), SYS_INT_POST_VER_FLAG_MASK(0x87F));
        SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE, SYS_INT_CAM_ENCAP_TYPE_MASK);
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_CANCEL;
        action.to_cpu = CTC_EXCP_DISCARD_AND_TO_CPU;
        SYS_DTEL_INT_CAM_SET(lchip, action);
        SYS_INT_CAM_SET_UDP_PROBE;

        /*valid INT Pkt : E bit  default to cancel session type */
        SYS_DTEL_INT_KEY_INIT;
        SYS_DTEL_INT_KEY_SET(zeroField0, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField1, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField2, 1, 1);
        SYS_DTEL_INT_KEY_SET(intType, CTC_PARSER_INT_TYPE_HOP_BY_HOP, 0xFF);
        SYS_DTEL_INT_KEY_SET(intVerFlag, SYS_INT_POST_VER_FLAG(0x100), SYS_INT_POST_VER_FLAG_MASK(0xF7F));
        SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE, SYS_INT_CAM_ENCAP_TYPE_MASK);
        sal_memset(&action, 0, sizeof(action));
        action.cam_idx = SYS_INT_HDRCAM_IDX_EBIT_EQ_1;
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_CANCEL;
        action.to_cpu = CTC_EXCP_NORMAL_FWD;
        SYS_DTEL_INT_CAM_SET(lchip, action);
        SYS_INT_CAM_SET_UDP_PROBE;

        SYS_DTEL_INT_KEY_INIT;
        sal_memset(&action, 0, sizeof(action));
        SYS_DTEL_INT_KEY_SET(zeroField0, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField1, 1, 1);
        SYS_DTEL_INT_KEY_SET(zeroField2, 1, 1);
        SYS_DTEL_INT_KEY_SET(remainHopThreshold, 0, 1);
        SYS_DTEL_INT_KEY_SET(intType, CTC_PARSER_INT_TYPE_HOP_BY_HOP, 0xFF);
        SYS_DTEL_INT_KEY_SET(intVerFlag, SYS_INT_POST_VER_FLAG(0), SYS_INT_POST_VER_FLAG_MASK(0xE7F));
        SYS_DTEL_INT_KEY_SET(intEncapType, SYS_INT_CAM_ENCAP_TYPE, SYS_INT_CAM_ENCAP_TYPE_MASK);
        action.cam_idx = SYS_INT_HDRCAM_IDX_EXCEED_RHC;
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_NONE;
        action.to_cpu =   CTC_EXCP_NORMAL_FWD;
        SYS_DTEL_INT_CAM_SET(lchip, action);
        SYS_INT_CAM_SET_UDP_PROBE;

        /*default entry, cancel int op*/
        SYS_DTEL_INT_KEY_INIT;
        sal_memset(&action, 0, sizeof(action));
        action.cam_idx = SYS_INT_HDRCAM_IDX_DEFAULT;
        action.session_type = CTC_DTEL_INT_SESSION_TYPE_NONE;
        action.to_cpu = CTC_EXCP_NORMAL_FWD;
        SYS_DTEL_INT_CAM_SET(lchip, action);

        /*Config default int session for cam use*/
        sal_memset(&int_cfg, 0, sizeof(ctc_dtel_int_cfg_t));
        int_cfg.session_id = 31;
        int_cfg.log_en = 1;
        int_cfg.log_id = 3;
        int_cfg.log_percent = CTC_LOG_PERCENT_POWER_NEGATIVE_0;
        int_cfg.rep_md_bits = CTC_DTEL_INT_REP_LV1_PORT | CTC_DTEL_INT_REP_HOP_LATENCY \
                            | CTC_DTEL_INT_REP_QUEUE_INFO | CTC_DTEL_INT_REP_EGR_TS | CTC_DTEL_INT_REP_EPTU;/* 0x2F */
        CTC_ERROR_RETURN(_sys_usw_dtel_set_int_cfg(lchip, &int_cfg));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_dtel_clear_inthdr_cam(lchip));
        sal_memset(&int_cfg, 0, sizeof(ctc_dtel_int_cfg_t));
        for (int_cfg.session_id = 0; int_cfg.session_id < CTC_DTEL_INT_SINK_SESSION_NUM; int_cfg.session_id++)
        {
            CTC_ERROR_RETURN(_sys_usw_dtel_set_int_cfg(lchip, &int_cfg));
        }
    }
    CTC_ERROR_RETURN(_sys_usw_dtel_set_fwd_register(lchip, enable));

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_dtel_init_int_edit(uint8 lchip, uint8 enable)
{
    DsIntSessionEdit_m int_edit;
    DsIntEditCtl_m epe_edit;
    sys_int_hdr_t  int_header;
    DsIntExtRewriteProfile_m  flex_edit;
    uint32 field_val = 0;
    uint8 loop = 0, loop2 = 0, md_loop = 0, step = 0;
    uint8 metadata_idx[2] = {0};
    uint16 ins_bmph = 0;
    uint8 encap_mode = 0;
    uint8 node_mode = 0;
    uint8 metadata_len = 0;
    uint8 is_ipv6 = 0, is_tcp = 0;
    uint8 flex_edit_idx = 0;
    uint32 cmd = 0;
    ParserLayer4AppCtl_m parser_int;
    uint8 probe_marker_mode = 0;
    uint16 dscp = 0;
    uint8 l4checksumsel = 0;
    uint8 set_zero = 0;
    uint8 l4ChksumUpdate = 0;
    uint8 l4ChksumUpdateX = 0;

    cmd = DRV_IOR(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));
    probe_marker_mode = GetParserLayer4AppCtl(V, udpProbeIntEn_f, &parser_int);

    /*DsIntEditCtl*/
    cmd = DRV_IOR(DsIntEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));
    SetDsIntEditCtl(V, intMaxRemoveLen_f, &epe_edit, enable ? 32 : 0);
    SetDsIntEditCtl(V, intMtuCheckSelectBits_f, &epe_edit, enable ? 4 : 0);
    SetDsIntEditCtl(V, dscpSelMode_f, &epe_edit, 0);
    SetDsIntEditCtl(V, level2PortMode_f, &epe_edit, 0);
    SetDsIntEditCtl(V, matedataInvalid_f, &epe_edit, enable ? 0xFFFFFFFF : 0);
    SetDsIntEditCtl(V, intStartPosTcp_f, &epe_edit, enable ? 10 : 0);
    SetDsIntEditCtl(V, intStartPosUdp_f, &epe_edit, enable ? 4 : 0);
    SetDsIntEditCtl(V, validInsBitmap1_f, &epe_edit, enable ? 0x00ff0003 : 0);
    SetDsIntEditCtl(V, validInsBitmap2_f, &epe_edit, enable ? 0x007fe000 : 0);
    SetDsIntEditCtl(V, validInsBitmap3_f, &epe_edit, enable ? 0x00ffffff : 0);
    SetDsIntEditCtl(V, intDscpMarkerMask_f, &epe_edit, 0);
    SetDsIntEditCtl(V, intDscpMarkerValue_f, &epe_edit, 0);
    SetDsIntEditCtl(V, intDscpMarkerValid_f, &epe_edit, 0);
    SetDsIntEditCtl(V, udpSourceEn_f, &epe_edit, enable ? 1 : 0);
    SetDsIntEditCtl(V, tcpSourceEn_f, &epe_edit, enable ? 1 : 0);
    SetDsIntEditCtl(V, intSinkOpFailDiscard_f , &epe_edit, 0);
    SetDsIntEditCtl(V, intSinkOpFailToException_f, &epe_edit, enable ? 1 : 0);
    SetDsIntEditCtl(V, ebitRewriteOpType_f , &epe_edit, enable ? 2 : 0);
    SetDsIntEditCtl(V, mbitRewriteOpType_f , &epe_edit, enable ? 2 : 0);
    if (DRV_FROM_AT(lchip))
    {/* enable flex edit, rewrite E bit or M bit */
        SetDsIntEditCtl(V, intEMBitRw_0_rwZoneEn_f , &epe_edit, enable ? 1 : 0);
        SetDsIntEditCtl(V, intEMBitRw_1_rwZoneEn_f , &epe_edit, enable ? 1 : 0);
    }

    step = DsIntEditCtl_intEMBitRw_1_rwValid_f - DsIntEditCtl_intEMBitRw_0_rwValid_f;
    for (loop = 0; loop < 2; loop++)
    {
        SetDsIntEditCtl(V, intEMBitRw_0_rwValid_f + step*loop , &epe_edit, enable ? 1 : 0);
        if (loop == 0)
        {
            SetDsIntEditCtl(V, intEMBitRw_0_rwData_f + step*loop , &epe_edit, enable ? 1 : 0);
            SetDsIntEditCtl(V, intEMBitRw_0_rwMask_f + step*loop , &epe_edit, enable ? 1 : 0);
            SetDsIntEditCtl(V, intEMBitRw_0_rwOffset_f + step*loop , &epe_edit, 0);
        }
        else
        {
            SetDsIntEditCtl(V, intEMBitRw_0_rwData_f + step*loop , &epe_edit, enable ? 0x80 : 0);
            SetDsIntEditCtl(V, intEMBitRw_0_rwMask_f + step*loop , &epe_edit, enable ? 0x80 : 0);
            SetDsIntEditCtl(V, intEMBitRw_0_rwOffset_f + step*loop , &epe_edit, enable ? 1 : 0);
        }
        SetDsIntEditCtl(V, intEMBitRw_0_rwZoneId_f + step*loop , &epe_edit, 0);
        SetDsIntEditCtl(V, intEMBitRw_0_rwShift_f + step*loop , &epe_edit, 0);
        SetDsIntEditCtl(V, intEMBitRw_0_rwAluEditId_f + step*loop , &epe_edit, enable ? 3 : 0);
        SetDsIntEditCtl(V, intEMBitRw_0_rwAluOpType_f + step*loop , &epe_edit, enable ? 3 : 0);
        SetDsIntEditCtl(V, intEMBitRw_0_l4ChksumUpdate_f + step*loop , &epe_edit, enable ? 1 : 0);
        SetDsIntEditCtl(V, intEMBitRw_0_l4ChecksumSel_f + step*loop , &epe_edit, 0);
        SetDsIntEditCtl(V, intEMBitRw_0_l4ChecksumMaskId_f + step*loop , &epe_edit, 0);
        SetDsIntEditCtl(V, intEMBitRw_0_intRwOffsetAdjust_f + step*loop , &epe_edit, enable ? 4 : 0);
        SetDsIntEditCtl(V, intEMBitRw_0_intForceL4ChecksumEqualZero_f + step*loop , &epe_edit, enable ? 1 : 0);
        cmd = DRV_IOW(DsIntEditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));
    }


    cmd = DRV_IOW(DsPktRwL3ChkSumMaskProfile_t, DsPktRwL3ChkSumMaskProfile_chksumMask_f);
    field_val = 0;
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    field_val = enable ? 0xFFFFFFFF : 0;
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 1, cmd, &field_val));
    field_val = enable ? 0xFFF00000 : 0;
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 2, cmd, &field_val));
    field_val = enable ? 0xFFF00000 : 0;
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 3, cmd, &field_val));

    cmd = DRV_IOW(DsPktRwL4ChkSumMaskProfile_t, DsPktRwL4ChkSumMaskProfile_chksumMask_f);
    field_val = 0;
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    field_val = enable ? 0xFFFFFFFF : 0;
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 1, cmd, &field_val));
    field_val = enable ? 0x000FFFFF : 0;
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 2, cmd, &field_val));
    field_val = enable ? 0x000FFFFF : 0;
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 3, cmd, &field_val));


    for (loop = 0; loop < ((SYS_INT_EDITMODE_SINK_TCPRAW+1)<<1); loop++)
    {
        encap_mode = (loop >> 1) & 3;/*Encap mode : 00-UDPPROBE;01-TCPPROBE; 10- UDPRAW;11-TCPRAW */
        node_mode =  (loop >> 3) & 3; /*INT Node mode : 00-source;01-transmit; 10- sink */
        is_ipv6 = loop & 0x1;
        is_tcp = encap_mode & 0x1;
        flex_edit_idx = ((loop&0xF8)>>1) | (is_ipv6? 0x0: 0x1) | (is_tcp? 0x0: 0x2);

        if (encap_mode == 0 || encap_mode == 1  )
        {/*00-UDPPROBE;01-TCPPROBE not support*/
            continue;
        }
        sal_memset(&flex_edit, 0, sizeof(DsIntExtRewriteProfile_m));

        cmd = DRV_IOR(DsIntExtRewriteProfile_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, flex_edit_idx, cmd, &flex_edit));
        l4checksumsel = GetDsIntExtRewriteProfile(V, l4ChecksumSel_f, &flex_edit);
        set_zero = GetDsIntExtRewriteProfile(V, intForceL4ChecksumEqualZero_f, &flex_edit);
        l4ChksumUpdate = GetDsIntExtRewriteProfile(V, l4ChksumUpdate_f, &flex_edit);
        l4ChksumUpdateX = GetDsIntExtRewriteProfile(V, l4ChksumUpdateX_f, &flex_edit);

        dscp = p_usw_dtel_master[lchip]->dscp ? p_usw_dtel_master[lchip]->dscp : (is_ipv6 ? 64 : 4);
        if (enable)
        {
            /*UDP over INT Packet always L4CheckSum equal to 0*/
            if (!(set_zero || l4checksumsel || l4ChksumUpdate || l4ChksumUpdateX))
            {
                SetDsIntExtRewriteProfile(V, l4ChecksumSel_f, &flex_edit, 0);
                SetDsIntExtRewriteProfile(V, intForceL4ChecksumEqualZero_f, &flex_edit, 1);
                SetDsIntExtRewriteProfile(V, l4ChksumUpdate_f, &flex_edit, 1);
                SetDsIntExtRewriteProfile(V, l4ChksumUpdateX_f, &flex_edit, 1);
            }
            SetDsIntExtRewriteProfile(V, adjustPktL3Length_f, &flex_edit, 1);
            SetDsIntExtRewriteProfile(V, adjustPktL4Length_f, &flex_edit, 1);

            switch (node_mode)
            {
                case 0: /*00-source */
                    SetDsIntExtRewriteProfile(V, l3ChecksumMaskId_f, &flex_edit, is_ipv6?0:2);
                    SetDsIntExtRewriteProfile(V, l4ChecksumMaskId_f, &flex_edit, is_ipv6?1:2);
                    SetDsIntExtRewriteProfile(V, l3ChksumUpdate_f, &flex_edit, is_ipv6?0:1);
                    SetDsIntExtRewriteProfile(V, l3ChecksumSel_f, &flex_edit, is_ipv6?0:6);
                    /*select word0 after l3offset*/
                    SetDsIntExtRewriteProfile(V, flex0LayerSelect_f, &flex_edit, 2);
                    SetDsIntExtRewriteProfile(V, flex0LayerOffset_f, &flex_edit, 0);
                    /*temp = temp&(~mask)|(data<<shift)&mask*/
                    SetDsIntExtRewriteProfile(V, data_f1Valid_f, &flex_edit, probe_marker_mode ? 0 : 1);/*8bit op*/
                    SetDsIntExtRewriteProfile(V, data_f1_0_pos_f, &flex_edit, 1);/*tos pos in byte*/
                    SetDsIntExtRewriteProfile(V, data_f1_0_shift_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_f1_0_zoneId_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_f1_0_data_f, &flex_edit, dscp);/*INT tos*/
                    SetDsIntExtRewriteProfile(V, data_f1_0_mask_f, &flex_edit, dscp);/*INT tos*/
                    /*0:4bit,1:8bit,2:16bit,3:32bit*/
                    SetDsIntExtRewriteProfile(V, data_alu_0_pendingContainerType_f, &flex_edit, 1);
                    SetDsIntExtRewriteProfile(V, data_alu_0_pendingAluOpType_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_alu_0_pendingEditId_f, &flex_edit, 0);

                    break;
                case 1:  /*01-transmit*/
                    SetDsIntExtRewriteProfile(V, l3ChksumUpdate_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, l3ChecksumSel_f, &flex_edit, is_ipv6?0:6);

                    SetDsIntExtRewriteProfile(V, flex0LayerSelect_f, &flex_edit, 3);
                    SetDsIntExtRewriteProfile(V, flex0LayerOffset_f, &flex_edit, probe_marker_mode ? (is_tcp?14:8) : (is_tcp?10:4));

                    SetDsIntExtRewriteProfile(V, data_f1Valid_f, &flex_edit, 12);
                   /*#Remaining Hop Count*/
                    SetDsIntExtRewriteProfile(V, data_f1_2_zoneId_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_f1_2_data_f, &flex_edit, 1);
                    SetDsIntExtRewriteProfile(V, data_f1_2_mask_f, &flex_edit, 0xff);
                    SetDsIntExtRewriteProfile(V, data_f1_2_pos_f, &flex_edit, ((1<<2)|3));
                    SetDsIntExtRewriteProfile(V, data_f1_2_shift_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_alu_2_pendingContainerType_f, &flex_edit, 1);
                    SetDsIntExtRewriteProfile(V, data_alu_2_pendingAluOpType_f, &flex_edit, 2);
                    SetDsIntExtRewriteProfile(V, data_alu_2_pendingEditId_f, &flex_edit, 2);

                    /*INT metadata header Length*/
                    SetDsIntExtRewriteProfile(V, data_f1_3_zoneId_f, &flex_edit, 0);
                    //SetDsIntExtRewriteProfile(V, data_f1_3_data_f, &flex_edit, 9);
                    SetDsIntExtRewriteProfile(V, alu3ForLen_f, &flex_edit, 0xff);
                    SetDsIntExtRewriteProfile(V, data_f1_3_mask_f, &flex_edit, 0xff);
                    SetDsIntExtRewriteProfile(V, data_f1_3_pos_f, &flex_edit, ((0<<2)|2));
                    SetDsIntExtRewriteProfile(V, data_f1_3_shift_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_alu_3_pendingContainerType_f, &flex_edit, 1);
                    SetDsIntExtRewriteProfile(V, data_alu_3_pendingAluOpType_f, &flex_edit, 1);
                    SetDsIntExtRewriteProfile(V, data_alu_3_pendingEditId_f, &flex_edit, 3);
                    break;
                case 2:  /*10- sink*/
                    SetDsIntExtRewriteProfile(V, l3ChecksumMaskId_f, &flex_edit, is_ipv6?0:3);
                    SetDsIntExtRewriteProfile(V, l4ChecksumMaskId_f, &flex_edit, is_ipv6?1:3);

                    SetDsIntExtRewriteProfile(V, l3ChksumUpdate_f, &flex_edit, is_ipv6?0:1);
                    SetDsIntExtRewriteProfile(V, l3ChecksumSel_f, &flex_edit, is_ipv6?0:6);

                    SetDsIntExtRewriteProfile(V, flex0LayerSelect_f, &flex_edit, 2);
                    SetDsIntExtRewriteProfile(V, flex0LayerOffset_f, &flex_edit, 0);

                    SetDsIntExtRewriteProfile(V, data_f1Valid_f, &flex_edit, probe_marker_mode ? 0 : 1);
                    SetDsIntExtRewriteProfile(V, data_f1_0_pos_f, &flex_edit, 2);
                    SetDsIntExtRewriteProfile(V, data_f1_0_shift_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_f1_0_zoneId_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_f1_0_data_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_f1_0_mask_f, &flex_edit, is_ipv6?64:4);
                    SetDsIntExtRewriteProfile(V, data_f1_0_pos_f, &flex_edit, 1);
                    SetDsIntExtRewriteProfile(V, data_f1_0_shift_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_alu_0_pendingAluOpType_f, &flex_edit, 0);
                    SetDsIntExtRewriteProfile(V, data_alu_0_pendingEditId_f, &flex_edit, 3);
                    break;
                default:
                    continue;
            }
        }
        cmd = DRV_IOW(DsIntExtRewriteProfile_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, flex_edit_idx, cmd, &flex_edit));
    }

    for (ins_bmph = 0; ins_bmph < (SYS_DTEL_INT_SUPPORT_INS_BITMAP+1); ins_bmph++)
    {
        sal_memset(&int_edit, 0, sizeof(DsIntSessionEdit_m));
        if (enable)
        {
            sal_memset(&int_header, 0, sizeof(sys_int_hdr_t));
            int_header.int_type = 1;
            int_header.remaining_hop_cnt = 64 - 1;
            int_header.ver = 1;

            SetDsIntSessionEdit(V, intProbeEn_f, &int_edit, probe_marker_mode);

            for (loop = 0, loop2 = 0; loop < SYS_DTEL_INT_SUPPORT_METADATA_NUM; loop++)
            {
                if (!CTC_IS_BIT_SET(ins_bmph, (SYS_DTEL_INT_SUPPORT_METADATA_NUM-1-loop)))
                {
                    continue;
                }
                _sys_usw_dtel_mapping_metadata_idx(lchip, 1 << loop, metadata_idx,&metadata_len);
                int_header.len += metadata_len;
                for (md_loop=0; md_loop<metadata_len; md_loop++)
                {
                    SetDsIntSessionEdit(V, g_0_intMdataIdx_f + loop2, &int_edit,  metadata_idx[md_loop]);
                    loop2++;
                }
            }
            int_header.hop_metadata_len =  int_header.len;
            int_header.len += 3;
            int_header.instruction_bitmap_1 = ins_bmph;
            int_header.instruction_bitmap_0 = 0;
            SetDsIntSessionEdit(A, intHeader_f, &int_edit, &int_header);
            SetDsIntSessionEdit(V, intMdNum_f, &int_edit, loop2);
        }
        cmd = DRV_IOW(DsIntSessionEdit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, ins_bmph, cmd, &int_edit));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_int_set_remaining_hop_cnt(uint8 lchip, uint8 cnt)
{
    DsIntSessionEdit_m int_edit;
    sys_int_hdr_t  int_header;
    uint16 ins_bmph = 0;
    uint32 cmd = 0;

    for (ins_bmph = 0; ins_bmph <= SYS_DTEL_INT_SUPPORT_INS_BITMAP; ins_bmph++)
    {
        cmd = DRV_IOR(DsIntSessionEdit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, ins_bmph, cmd, &int_edit));
        GetDsIntSessionEdit(A, intHeader_f, &int_edit, &int_header);
        int_header.remaining_hop_cnt = cnt;
        SetDsIntSessionEdit(A, intHeader_f, &int_edit, &int_header);
        cmd = DRV_IOW(DsIntSessionEdit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, ins_bmph, cmd, &int_edit));
    }
    return CTC_E_NONE;
}
extern int32
sys_usw_dma_set_chan_en(uint8 lchip, uint8 chan_id, uint8 chan_en);
extern int32
sys_usw_dma_get_chan_en(uint8 lchip, uint8 chan_id, uint8* chan_en);

#define SYS_ENCODE_TDX_HDR0(TP) (CTC_TDX_VER << 28) | ((TP) << 20)
STATIC int32
_sys_usw_dtel_tsx_set_cfg(uint8 lchip, ctc_dtel_tsx_cfg_t* p_cfg)
{
    sys_nh_info_dsnh_t nh_info;
    uint8 is_encap = 0;
    sys_usw_dma_export_map_t dma_map;
    sys_usw_dma_export_pkt_cfg_t export_cfg;

    sal_memset(&nh_info, 0, sizeof(sys_nh_info_dsnh_t));
    if(p_cfg->nh_id)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_cfg->nh_id, &nh_info, 0));
        if (nh_info.nh_entry_type != SYS_NH_TYPE_IP_TUNNEL)
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    sal_memset(&export_cfg, 0, sizeof(sys_usw_dma_export_pkt_cfg_t));
    sal_memset(&dma_map, 0, sizeof(sys_usw_dma_export_map_t));

    switch (p_cfg->type)
    {
       case CTC_DTEL_TSX_BUFFER_STATS:
            (p_cfg->nh_id && p_cfg->enable) ? CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_DMA_EXP) : CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_CPU);
            dma_map.type = SYS_DMA_REPORT_TYPE_IRM0;
            CTC_ERROR_RETURN(sys_usw_dma_export_map(lchip, &dma_map));
            dma_map.type = SYS_DMA_REPORT_TYPE_IRM1;
            CTC_ERROR_RETURN(sys_usw_dma_export_map(lchip, &dma_map));
            if(!DRV_FROM_AT(lchip))
            {
                dma_map.type = SYS_DMA_REPORT_TYPE_ERM_STATS;
                CTC_ERROR_RETURN(sys_usw_dma_export_map(lchip, &dma_map));
            }
            export_cfg.metadata[0] = SYS_ENCODE_TDX_HDR0(CTC_TDX_TYPE_BUFFER_STATS);
            is_encap = 1;
            break;
        case CTC_DTEL_TSX_LATENCY_STATS:
            (p_cfg->nh_id && p_cfg->enable) ? CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_DMA_EXP) : CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_CPU);
            dma_map.type = SYS_DMA_REPORT_TYPE_LATENCY_STATS;
            CTC_ERROR_RETURN(sys_usw_dma_export_map(lchip, &dma_map));
            export_cfg.metadata[0] = SYS_ENCODE_TDX_HDR0(CTC_TDX_TYPE_LATENCY_STATS);
            is_encap = 1;
            break;
        default:
            return CTC_E_NOT_SUPPORT;
    }

    if (p_cfg->nh_id && is_encap)
    {
        export_cfg.fifo_id = dma_map.fifo_id;
        export_cfg.metadata[1] = 0x0;
        export_cfg.metadata[2] = p_usw_dtel_master[lchip]->switch_id;
        export_cfg.end_tlv = 0;
        export_cfg.nhid = p_cfg->nh_id;
        export_cfg.interval = (uint64)p_cfg->interval * 1000000;/* ms to ns */
        CTC_ERROR_RETURN(sys_usw_dma_export_pkt_cfg(lchip, &export_cfg));
    }
    p_usw_dtel_master[lchip]->tsx_nh_id[p_cfg->type] = p_cfg->enable ? p_cfg->nh_id : 0;
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_dtel_tsx_get_cfg(uint8 lchip, ctc_dtel_tsx_cfg_t* p_cfg)
{
    uint32 cmd = 0;
    uint32 interval[2];
    EncapMeterCfg_m encap_cfg;
    switch (p_cfg->type)
    {
        case CTC_DTEL_TSX_BUFFER_STATS:
        case CTC_DTEL_TSX_LATENCY_STATS:
            p_cfg->enable = p_usw_dtel_master[lchip]->tsx_nh_id[p_cfg->type]?1:0;
            p_cfg->nh_id = p_usw_dtel_master[lchip]->tsx_nh_id[p_cfg->type];
            cmd = DRV_IOR(EncapMeterCfg_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &encap_cfg));
            GetEncapMeterCfg(A, encapMeter_1_timer_f, &encap_cfg, interval);/* buffer/latency use encap fifo 1 */
            p_cfg->interval = (((uint64)interval[1] << 32) + interval[0]) / 1000000;
            break;
        default:
            return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

#if defined E_UNIT && (FEATURE_MODE == 0)
STATIC int32
_sys_usw_dtel_drop_pkt_redirect_eunit(uint8 lchip, uint8 enable)
{
    uint32 value = 0;
    uint32 cmd = 0;
    uint8  unit = 0;
    uint8 gchip = 0;
    uint32 gport = 0;
    ctc_qos_queue_cfg_t que_cfg;
    ctc_qos_shape_t shape;
    IpeFwdCtl_m ipe_fwd_ctl;
    EpeHeaderEditCtl_m epe_edit_ctl;
    uint32 discard_bmp[2] = {0xFFFFFFFE, 0xFFFFFFFF};

    sal_memset(&shape, 0, sizeof(ctc_qos_shape_t));
    sal_memset(&que_cfg, 0, sizeof(ctc_qos_queue_cfg_t));

    if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
    {
        sys_usw_get_gchip_id(lchip, &gchip);
        gport = CTC_MAP_LPORT_TO_GPORT(gchip, (unit == SYS_EUNIT_E) ? SYS_RSV_PORT_EUNIT0_ID : SYS_RSV_PORT_EUNIT1_ID);
    }
    cmd = DRV_IOR(IpeFwdCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_fwd_ctl));
    cmd = DRV_IOR(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit_ctl));

    if (enable)
    {
        if (!DRV_FROM_AT(lchip))
        {
            CTC_ERROR_RETURN(sys_usw_brguc_nh_create(lchip, gport, CTC_NH_PARAM_BRGUC_SUB_TYPE_ALL));
            /* Shape */
            shape.type = CTC_QOS_SHAPE_PORT;
            shape.shape.port_shape.enable = 1;
            shape.shape.port_shape.gport = gport;
            shape.shape.port_shape.pir = 50000;/* 50M */
            shape.shape.port_shape.pbs = 0xFFFFFFFF;
            CTC_ERROR_RETURN(sys_usw_qos_set_shape(lchip, &shape));
            /*CTC_PKT_CPU_REASON_DIAG_DISCARD_PKT dest-to Eunit*/
            que_cfg.type = CTC_QOS_QUEUE_CFG_QUEUE_REASON_DEST;
            que_cfg.value.reason_dest.cpu_reason = CTC_PKT_CPU_REASON_DIAG_DISCARD_PKT;
            que_cfg.value.reason_dest.dest_type = CTC_PKT_CPU_REASON_TO_LOCAL_PORT;
            que_cfg.value.reason_dest.dest_port = gport;
            CTC_ERROR_RETURN(sys_usw_qos_set_queue(lchip, &que_cfg));
        }

        /*IPE*/
        /*ipe discard type 0, used for iLoop drop*/
        SetIpeFwdCtl(V, discardEventLogEn_f, &ipe_fwd_ctl, 1);
        SetIpeFwdCtl(V, discardEventLogWithDiscardType_f, &ipe_fwd_ctl, 1);
        SetIpeFwdCtl(A, discardEventLogEnBitmap_f, &ipe_fwd_ctl, discard_bmp);
        cmd = DRV_IOW(IpeFwdCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_fwd_ctl));

        /*EPE*/
        SetEpeHeaderEditCtl(V, discardEventLogEn_f, &epe_edit_ctl, 1);
        SetEpeHeaderEditCtl(V, discardEventLogWithDiscardType_f, &epe_edit_ctl, 1);
        SetEpeHeaderEditCtl(A, discardEventLogEnBitmap_f, &epe_edit_ctl, discard_bmp);

        value = GetEpeHeaderEditCtl(V, logOnDiscard_f, &epe_edit_ctl);
        /* Set discardEventLogEn */
        CTC_BIT_SET(value, 7);
        SetEpeHeaderEditCtl(V, logOnDiscard_f, &epe_edit_ctl, value);
        cmd = DRV_IOW(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit_ctl));
    }
    else
    {
        /*IPE*/
        sal_memset(discard_bmp,0, sizeof(discard_bmp));
        SetIpeFwdCtl(V, discardEventLogEn_f, &ipe_fwd_ctl, 0);
        SetIpeFwdCtl(V, discardEventLogWithDiscardType_f, &ipe_fwd_ctl, 0);
        SetIpeFwdCtl(A, discardEventLogEnBitmap_f, &ipe_fwd_ctl, discard_bmp);

        cmd = DRV_IOW(IpeFwdCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_fwd_ctl));

        /*EPE*/
        SetEpeHeaderEditCtl(V, discardEventLogEn_f, &epe_edit_ctl, 0);
        SetEpeHeaderEditCtl(V, discardEventLogWithDiscardType_f, &epe_edit_ctl, 0);
        SetEpeHeaderEditCtl(A, discardEventLogEnBitmap_f, &epe_edit_ctl, discard_bmp);

        value = GetEpeHeaderEditCtl(V, logOnDiscard_f, &epe_edit_ctl);
        /* Set discardEventLogEn */
        CTC_BIT_UNSET(value, 7);
        SetEpeHeaderEditCtl(V, logOnDiscard_f, &epe_edit_ctl, value);
        cmd = DRV_IOW(EpeHeaderEditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit_ctl));

        /*CTC_PKT_CPU_REASON_DIAG_DISCARD_PKT dest-to Eunit*/
        que_cfg.type = CTC_QOS_QUEUE_CFG_QUEUE_REASON_DEST;
        que_cfg.value.reason_dest.cpu_reason = CTC_PKT_CPU_REASON_DIAG_DISCARD_PKT;
        que_cfg.value.reason_dest.dest_type = CTC_PKT_CPU_REASON_TO_DROP;
        CTC_ERROR_DUMP(sys_usw_qos_set_queue(lchip, &que_cfg));
        sys_usw_brguc_nh_delete(lchip, gport);
        /* Shape */
        shape.type = CTC_QOS_SHAPE_PORT;
        shape.shape.port_shape.enable = 0;
        shape.shape.port_shape.gport = gport;
        CTC_ERROR_DUMP(sys_usw_qos_set_shape(lchip, &shape));
    }

    return CTC_E_NONE;
}
#endif

STATIC int32
_sys_usw_dtel_tex_set_cfg(uint8 lchip, ctc_dtel_tex_cfg_t* p_cfg)
{
    sys_nh_info_dsnh_t nh_info;
    sys_usw_dma_export_map_t dma_map;
    sys_usw_dma_export_pkt_cfg_t export_cfg;
    uint8 is_encap = 0;

    sal_memset(&nh_info, 0, sizeof(sys_nh_info_dsnh_t));
    if(p_cfg->nh_id)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_cfg->nh_id, &nh_info, 0));
        if (nh_info.nh_entry_type != SYS_NH_TYPE_IP_TUNNEL)
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    sal_memset(&export_cfg, 0, sizeof(sys_usw_dma_export_pkt_cfg_t));
    sal_memset(&dma_map, 0, sizeof(sys_usw_dma_export_map_t));

    switch (p_cfg->type)
    {
        case CTC_DTEL_TEX_DROP_EVENT:
            return CTC_E_NONE;
        case CTC_DTEL_TEX_BUFFER_EVENT:
            p_cfg->nh_id ? CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_DMA_EXP) : CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_CPU);

            dma_map.type = SYS_DMA_REPORT_TYPE_ERM_EVENT;

            CTC_ERROR_RETURN(sys_usw_dma_export_map(lchip, &dma_map));
            export_cfg.metadata[0] = SYS_ENCODE_TDX_HDR0(CTC_TDX_TYPE_BUFFER_EVENT);
            is_encap = 1;
            break;
        case CTC_DTEL_TEX_LATENCY_EVENT:
            p_cfg->nh_id ? CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_DMA_EXP) : CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_CPU);

            dma_map.type = SYS_DMA_REPORT_TYPE_LATENCY_EVENT;
            CTC_ERROR_RETURN(sys_usw_dma_export_map(lchip, &dma_map));
            export_cfg.metadata[0] = SYS_ENCODE_TDX_HDR0(CTC_TDX_TYPE_LATENCY_EVENT);
            is_encap = 1;
            break;
        default:
            return CTC_E_NOT_SUPPORT;
    }

    if (p_cfg->nh_id && is_encap)
    {
        export_cfg.fifo_id = dma_map.fifo_id;
        export_cfg.metadata[1] = 0x0;
        export_cfg.metadata[2] = p_usw_dtel_master[lchip]->switch_id;
        export_cfg.end_tlv = 0;
        export_cfg.nhid = p_cfg->nh_id;
        CTC_ERROR_RETURN(sys_usw_dma_export_pkt_cfg(lchip, &export_cfg));
    }
    p_usw_dtel_master[lchip]->tex_nh_id[p_cfg->type] = p_cfg->nh_id;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_tex_get_cfg(uint8 lchip, ctc_dtel_tex_cfg_t* p_cfg)
{
    switch (p_cfg->type)
    {
        case CTC_DTEL_TEX_DROP_EVENT:
            return CTC_E_NONE;
        case CTC_DTEL_TEX_BUFFER_EVENT:
        case CTC_DTEL_TEX_LATENCY_EVENT:
            p_cfg->nh_id = p_usw_dtel_master[lchip]->tex_nh_id[p_cfg->type];
            return CTC_E_NONE;
            break;
        default:
            return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_tix_set_cfg(uint8 lchip, ctc_dtel_tix_cfg_t* p_cfg)
{
    sys_nh_info_dsnh_t nh_info;
    uint8 idx = 0;
    sys_usw_dma_export_map_t dma_map;
    sys_usw_dma_export_pkt_cfg_t export_cfg;

    sal_memset(&nh_info, 0, sizeof(sys_nh_info_dsnh_t));
    sal_memset(&export_cfg, 0, sizeof(sys_usw_dma_export_pkt_cfg_t));
    sal_memset(&dma_map, 0, sizeof(sys_usw_dma_export_map_t));
    if(p_cfg->nh_id)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_cfg->nh_id, &nh_info, 0));
        if (nh_info.nh_entry_type != SYS_NH_TYPE_IP_TUNNEL)
        {
            return CTC_E_INVALID_PARAM;
        }

        if(p_cfg->eunit_en)
        {
            CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_EUNIT);
        }
        else 
        {
            CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_DMA_EXP);
        }
    }
    else
    {
        CTC_BIT_SET(dma_map.dest_bmp, SYS_DMA_EXP_DEST_TYPE_CPU);
    }

    switch (p_cfg->type)
    {
        case CTC_DTEL_TIX_IPFIX:
            for (idx = SYS_DMA_REPORT_TYPE_IPFIX_IGS_START; idx <= SYS_DMA_REPORT_TYPE_IPFIX_EGS_END; idx++)
            {
                dma_map.type = idx;
                CTC_ERROR_RETURN(sys_usw_dma_export_map(lchip, &dma_map));
            }
            export_cfg.metadata[0] = SYS_ENCODE_TDX_HDR0(CTC_TDX_TYPE_IPFIX);
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    if (p_cfg->nh_id)
    {
        export_cfg.fifo_id = dma_map.fifo_id;
        export_cfg.metadata[1] = 0x0;
        export_cfg.metadata[2] = p_usw_dtel_master[lchip]->switch_id;
        export_cfg.end_tlv = 0;
        export_cfg.nhid = p_cfg->nh_id;
        CTC_ERROR_RETURN(sys_usw_dma_export_pkt_cfg(lchip, &export_cfg));
    }
    p_usw_dtel_master[lchip]->tix_nh_id[p_cfg->type] = p_cfg->nh_id;
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_tix_get_cfg(uint8 lchip, ctc_dtel_tix_cfg_t* p_cfg)
{
#if defined E_UNIT && (FEATURE_MODE == 0)
    uint32 cmd = 0;
    MapMsgDestMap_m msg_map;

    sal_memset(&msg_map, 0, sizeof(MapMsgDestMap_m));
    cmd = DRV_IOR(MapMsgDestMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &msg_map));
    p_cfg->eunit_en = GetMapMsgDestMap(V, ecpu0En_f, &msg_map);
#endif

    p_cfg->nh_id = p_usw_dtel_master[lchip]->tix_nh_id[p_cfg->type];
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_dtel_int_init_db(uint8 lchip)
{
    int32 ret = 0;
    uint64 cpu_mask = 0;

    if (p_usw_dtel_master[lchip]->sink_sem)
    {
        return CTC_E_NONE;
    }
    CTC_ERROR_DUMP(sal_sem_create(&p_usw_dtel_master[lchip]->sink_sem, 0));
    CTC_ERROR_RETURN(NULL == p_usw_dtel_master[lchip]->sink_sem? CTC_E_NO_MEMORY: CTC_E_NONE);

    sal_mutex_create(&p_usw_dtel_master[lchip]->sink_mutex);
    if (NULL == p_usw_dtel_master[lchip]->sink_mutex)
    {
        sal_sem_destroy(p_usw_dtel_master[lchip]->sink_sem);
        p_usw_dtel_master[lchip]->sink_sem = NULL;
        return CTC_E_NO_RESOURCE;
    }

    p_usw_dtel_master[lchip]->int_rep_info = ctc_hash_create(SYS_DTEL_REP_HASH_SIZE, \
                    CTC_HASH_32_BLOCK_SIZE, \
                    (hash_key_fn)_sys_usw_dtel_rep_hash_make, \
                    (hash_cmp_fn)_sys_usw_dtel_rep_hash_compare);
    if (NULL == p_usw_dtel_master[lchip]->int_rep_info)
    {
        sal_sem_destroy(p_usw_dtel_master[lchip]->sink_sem);
        p_usw_dtel_master[lchip]->sink_sem = NULL;
        sal_mutex_destroy(p_usw_dtel_master[lchip]->sink_mutex);
        p_usw_dtel_master[lchip]->sink_mutex = NULL;
        return CTC_E_NO_MEMORY;
    }

    cpu_mask = sys_usw_chip_get_affinity(lchip, 0);
    ret = sys_usw_task_create(lchip, &p_usw_dtel_master[lchip]->sink_rep, \
                                       "INT report",\
                                       SAL_DEF_TASK_STACK_SIZE, \
                                       SAL_TASK_PRIO_DEF, \
                                       SAL_TASK_TYPE_OTHERS, \
                                       cpu_mask, _sys_usw_dtel_rep_task, \
                                       (void*)(uintptr)lchip);

    if (ret < 0)
    {
        sal_sem_destroy(p_usw_dtel_master[lchip]->sink_sem);
        p_usw_dtel_master[lchip]->sink_sem = NULL;
        sal_mutex_destroy(p_usw_dtel_master[lchip]->sink_mutex);
        p_usw_dtel_master[lchip]->sink_mutex = NULL;
        ctc_hash_free(p_usw_dtel_master[lchip]->int_rep_info);
        p_usw_dtel_master[lchip]->int_rep_info = NULL;
        return CTC_E_NO_MEMORY;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_int_deinit_db(uint8 lchip)
{
    SYS_DTEL_SINK_LOCK(lchip);
    ctc_hash_free2(p_usw_dtel_master[lchip]->int_rep_info, _sys_usw_dtel_rep_hash_free_node, NULL);
    SYS_DTEL_SINK_UNLOCK(lchip);
    p_usw_dtel_master[lchip]->int_rep_info = NULL;
    if (p_usw_dtel_master[lchip]->sink_sem)
    {
        sal_sem_give(p_usw_dtel_master[lchip]->sink_sem);
    }
    if (p_usw_dtel_master[lchip]->sink_rep)
    {
        sal_task_destroy(p_usw_dtel_master[lchip]->sink_rep);
        p_usw_dtel_master[lchip]->sink_rep = NULL;
    }
    if (p_usw_dtel_master[lchip]->sink_sem)
    {
        sal_sem_destroy(p_usw_dtel_master[lchip]->sink_sem);
        p_usw_dtel_master[lchip]->sink_sem = NULL;
    }
    if (p_usw_dtel_master[lchip]->sink_mutex)
    {
        sal_mutex_destroy(p_usw_dtel_master[lchip]->sink_mutex);
        p_usw_dtel_master[lchip]->sink_mutex = NULL;
    }

    return CTC_E_NONE;
}

STATIC int32 
_sys_usw_dtel_ifa_inband_md_edit(uint8 lchip, uint8 enable, uint8 version)
{
    DsIntEditCtl_m epe_edit;
    EpePktRw16BitCtl_m rw16;
    uint32 cmd = 0;
    
    cmd = DRV_IOR(DsIntEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));
    if(0 == version || 2 == version)
    {
        SetDsIntEditCtl(V, intStartPosUdp_f, &epe_edit, 0);
        SetDsIntEditCtl(V, intStartPosTcp_f, &epe_edit, enable ? 6 : 0);
    }
    else if(1 == version)
    {
        SetDsIntEditCtl(V, intStartPosTcp_f, &epe_edit, enable ? 14 : 0);
        SetDsIntEditCtl(V, intStartPosUdp_f, &epe_edit, enable ? 8 : 0);
    }
    SetDsIntEditCtl(V, switchInfo0_f, &epe_edit, enable);
    SetDsIntEditCtl(V, switchInfo1_f, &epe_edit, enable);
    SetDsIntEditCtl(V, udpSourceEn_f, &epe_edit, enable);
    SetDsIntEditCtl(V, tcpSourceEn_f, &epe_edit, enable);
    cmd = DRV_IOW(DsIntEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));

    cmd = DRV_IOR(EpePktRw16BitCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rw16));
    SetEpePktRw16BitCtl(V, g_0_mask_f + 0, &rw16, 0xFFFF);
    cmd = DRV_IOW(EpePktRw16BitCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rw16));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_ifa_get_mode_cfg(uint8 lchip, ctc_dtel_ifa_mode_cfg_t* p_mode_cfg)
{
    DsIntSessionEdit_m int_edit;
    uint32 cmd = 0;
    uint32 index;
    uint8 loop = 0;
    uint8 req_vec = 0, len = 0;
    uint8 req_num = 0;
    p_mode_cfg->version = p_usw_dtel_master[lchip]->ifa_ver ? p_usw_dtel_master[lchip]->ifa_ver : 2;

    cmd =  DRV_IOR(DsIntSessionEdit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, SYS_DTEL_IFA_SUPPORT_REQUEST_VECTOR, cmd, &int_edit));
    do
    {
        index = GetDsIntSessionEdit(V, g_0_intMdataIdx_f + loop, &int_edit);
        _sys_usw_dtel_ifa_get_metadata_idx_mapping(lchip, index, &req_vec, &len);
        if(len)
        {
            p_mode_cfg->req_vec[req_num++] = req_vec;
        }
        loop += (len ? len : 1);
    }while((loop <= SYS_DTEL_INT_MAX_METADATA_INDEX) && (req_num < CTC_DTEL_IFA_REQ_VEC_BIT_NUM));
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_ifa_inband_hdr_edit(uint8 lchip, uint8 enable, uint8 version)
{
    DsIntExtRewriteProfile_m  flex_edit;
    uint32 cmd = 0;
    uint8 loop = 0;
    uint8 encap_mode = 0, node_mode = 0;
    int8 is_ipv6 = 0, is_tcp = 0;
    uint8 flex_edit_idx = 0;
    
    for (loop = 0; loop < ((SYS_INT_EDITMODE_SINK_TCPRAW+1)<<1); loop++)
    {
        encap_mode = (loop >> 1) & 3;/*Encap mode : 00-UDPPROBE;01-TCPPROBE; 10- UDPRAW;11-TCPRAW */
        node_mode =  (loop >> 3) & 3; /*INT Node mode : 00-source;01-transmit; 10- sink */
        is_ipv6 = loop & 0x1;
        is_tcp = encap_mode & 0x1;
        flex_edit_idx = ((loop&0xF8)>>1) | (is_ipv6? 0x0: 0x1) | (is_tcp? 0x0: 0x2);

        sal_memset(&flex_edit, 0, sizeof(DsIntExtRewriteProfile_m));
        /*only support transit node*/
        if(node_mode == 1 && enable)
        {
            /* udp checksum always be zero*/
            SetDsIntExtRewriteProfile(V, intForceL4ChecksumEqualZero_f, &flex_edit, 1);
            SetDsIntExtRewriteProfile(V, adjustPktL3Length_f, &flex_edit, 1);
            SetDsIntExtRewriteProfile(V, adjustPktL4Length_f, &flex_edit, 1);
            SetDsIntExtRewriteProfile(V, l4ChksumUpdateX_f, &flex_edit, 1);
            
            SetDsIntExtRewriteProfile(V, flex0LayerSelect_f, &flex_edit, 3);
            SetDsIntExtRewriteProfile(V, data_f1Valid_f, &flex_edit, 9);
            SetDsIntExtRewriteProfile(V, data_f1_0_zoneId_f, &flex_edit, 0);
            SetDsIntExtRewriteProfile(V, data_f1_0_data_f, &flex_edit, 1);
            SetDsIntExtRewriteProfile(V, data_f1_0_mask_f, &flex_edit, 0xFF);
            SetDsIntExtRewriteProfile(V, data_f1_0_shift_f, &flex_edit, 0);
            SetDsIntExtRewriteProfile(V, data_alu_0_pendingEditId_f, &flex_edit, 0);
            SetDsIntExtRewriteProfile(V, data_alu_0_pendingContainerType_f, &flex_edit, 1);

            SetDsIntExtRewriteProfile(V, data_f1_3_zoneId_f, &flex_edit, 0);
            SetDsIntExtRewriteProfile(V, alu3ForLen_f, &flex_edit, 0xff);
            SetDsIntExtRewriteProfile(V, data_f1_3_mask_f, &flex_edit, 0xff);
            SetDsIntExtRewriteProfile(V, data_f1_3_shift_f, &flex_edit, 0);
            SetDsIntExtRewriteProfile(V, data_alu_3_pendingAluOpType_f, &flex_edit, 1);
            SetDsIntExtRewriteProfile(V, data_alu_3_pendingEditId_f, &flex_edit, 3);
            SetDsIntExtRewriteProfile(V, data_alu_3_pendingContainerType_f, &flex_edit, 1);
            
            if(0 == version || 2 == version)
            {
                SetDsIntExtRewriteProfile(V, l4ChksumUpdate_f, &flex_edit, 1);
                SetDsIntExtRewriteProfile(V, data_f1_0_pos_f, &flex_edit, is_tcp ? 0x16 : 0x0A);
                SetDsIntExtRewriteProfile(V, data_alu_0_pendingAluOpType_f, &flex_edit, 2);
                SetDsIntExtRewriteProfile(V, data_f1_3_pos_f, &flex_edit, is_tcp ? 0x17: 0x0B);
            }
            else if(1 == version)
            {
                SetDsIntExtRewriteProfile(V, l4ChksumUpdate_f, &flex_edit, is_tcp ? 0 : 1);
                SetDsIntExtRewriteProfile(V, data_f1_0_pos_f, &flex_edit, is_tcp ? 0x25 : 0x19);
                SetDsIntExtRewriteProfile(V, data_alu_0_pendingAluOpType_f, &flex_edit, 1);
                SetDsIntExtRewriteProfile(V, data_f1_3_pos_f, &flex_edit, is_tcp ? 0x2b : 0x1f);
            }
            cmd = DRV_IOW(DsIntExtRewriteProfile_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, flex_edit_idx, cmd, &flex_edit));
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_set_ifa_en(uint8 lchip, uint8 enable)
{
    ParserIpCtl_m parserIp;
    ParserLayer4AppCtl_m parser_int;
    uint32 cmd = 0, value = 0;
    uint8 version = p_usw_dtel_master[lchip]->ifa_ver;
    
    CTC_MAX_VALUE_CHECK(enable, 1);
    if (p_usw_dtel_master[lchip]->inband_en || p_usw_dtel_master[lchip]->postcard_en)
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "INT is enabled. Cannot support IFA.\n");
        return CTC_E_INVALID_CONFIG;
    }

    if (!(enable ^ p_usw_dtel_master[lchip]->ifa_en))
    {
        return CTC_E_NONE;
    }
    /*IFA 2.0 */
    if(0 == version || 2 == version)
    {
        cmd = DRV_IOR(ParserIpCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parserIp));

        if ((GetParserIpCtl(V, ipv4ExtHdr0ProtocolEn_f, &parserIp) && GetParserIpCtl(V, ipv4ExtHdr0Type_f, &parserIp) != SYS_PARSER_L3_EXT_TYPE_IFA)
           || GetParserIpCtl(V, ipv4ExtHdr1ProtocolEn_f, &parserIp))
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Conflict configure with HMAC.\n");
            return CTC_E_INVALID_CONFIG;
        }

        value = GetParserIpCtl(V, l3ExtDataEn_f, &parserIp);
        enable ? CTC_BIT_SET(value, SYS_PARSER_L3_EXT_TYPE_IFA) : CTC_BIT_UNSET(value, SYS_PARSER_L3_EXT_TYPE_IFA);
        SetParserIpCtl(V, l3ExtDataEn_f, &parserIp, value);
        
        SetParserIpCtl(V, ipv4ExtHdr0ProtocolEn_f, &parserIp, enable);
        SetParserIpCtl(V, ipv4ExtHdr0Protocol_f, &parserIp, enable ? SYS_DTEL_IFA_PROTOCOL : 0);
        SetParserIpCtl(V, ipv4ExtHdr0Len_f, &parserIp, enable ? SYS_DTEL_IFA_BASE_HDR_LEN : 0);
        SetParserIpCtl(V, ipv4OptionLenType_f, &parserIp, 0);
        SetParserIpCtl(V, ipv4ExtHdr0Type_f, &parserIp, enable ? SYS_PARSER_L3_EXT_TYPE_IFA : 0);
        SetParserIpCtl(V, ipOptionMask_f, &parserIp, 0);
        SetParserIpCtl(V, ipOptionValue_f, &parserIp, 0);
        SetParserIpCtl(V, gL3ExtType_3_typeValue_f, &parserIp, enable);

        SetParserIpCtl(V, ipv6ExtHdr1Offset_f, &parserIp, enable);
        SetParserIpCtl(V, ipv6ExtHdr1LenType_f, &parserIp, enable);
        SetParserIpCtl(V, ipv6ExtHdr1ProtocolEn_f, &parserIp, enable);
        SetParserIpCtl(V, ipv6ExtHdr1Protocol_f, &parserIp, enable ? SYS_DTEL_IFA_PROTOCOL : 0);
        SetParserIpCtl(V, ipv6ExtHdr1Len_f, &parserIp, enable ? SYS_DTEL_IFA_BASE_HDR_LEN : 0);
        SetParserIpCtl(V, ipv6ExtHdr1Type_f, &parserIp, enable ? SYS_PARSER_L3_EXT_TYPE_IFA : 0);
        SetParserIpCtl(V, gL3ExtType_7_typeValue_f, &parserIp, enable);
        cmd = DRV_IOW(ParserIpCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parserIp));

        /*edit*/
        CTC_ERROR_RETURN(_sys_usw_dtel_ifa_inband_md_edit(lchip, enable, version));
        CTC_ERROR_RETURN(_sys_usw_dtel_ifa_inband_hdr_edit(lchip, enable, version));

        _sys_usw_dtel_set_fwd_register(lchip, enable);
        if (!enable)
        {
            uint8 idx = 0;
            DsIntIgrSinkSession_m igs_session;
            DsIntEgrSinkSession_m egs_session;
            sal_memset(&igs_session, 0, sizeof(DsIntIgrSinkSession_m));
            sal_memset(&egs_session, 0, sizeof(DsIntEgrSinkSession_m));

            for (idx = 0; idx < CTC_DTEL_IFA_SESSION_NUM; idx++)
            {
                cmd = DRV_IOW(DsIntIgrSinkSession_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, idx, cmd, &igs_session));
                cmd = DRV_IOW(DsIntEgrSinkSession_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, idx, cmd, &egs_session));
            }
            mem_free(p_usw_dtel_master[lchip]->ifa_session);
        }
        else
        {
            p_usw_dtel_master[lchip]->ifa_session = mem_malloc(MEM_DTEL_MODULE, CTC_DTEL_IFA_SESSION_NUM * sizeof(sys_dtel_ifa_session_t));
            if (NULL == p_usw_dtel_master[lchip]->ifa_session)
            {
                _sys_usw_dtel_set_fwd_register(lchip, !enable);
                return CTC_E_NO_MEMORY;
            }
            sal_memset(p_usw_dtel_master[lchip]->ifa_session, 0, CTC_DTEL_IFA_SESSION_NUM * sizeof(sys_dtel_ifa_session_t));
        }

    }
    /*IFA 1.0 inband probemarker */
    else if(1 == version)
    {
        /*parser*/
        cmd = DRV_IOR(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));
        SetParserLayer4AppCtl(V, intIpv4UdpProbeMarkEn_f, &parser_int, enable);
        SetParserLayer4AppCtl(V, intIpv6UdpProbeMarkEn_f, &parser_int, enable);
        SetParserLayer4AppCtl(V, intIpv4TcpProbeMarkEn_f, &parser_int, enable);
        SetParserLayer4AppCtl(V, intIpv6TcpProbeMarkEn_f, &parser_int, enable);
        SetParserLayer4AppCtl(V, intIpv4UdpTosMarkEn_f, &parser_int, 0);
        SetParserLayer4AppCtl(V, intIpv6UdpTosMarkEn_f, &parser_int, 0);
        SetParserLayer4AppCtl(V, intIpv4TcpTosMarkEn_f, &parser_int, 0);
        SetParserLayer4AppCtl(V, intIpv6TcpTosMarkEn_f, &parser_int, 0);
        cmd = DRV_IOW(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));

        /*edit*/
        CTC_ERROR_RETURN(_sys_usw_dtel_ifa_inband_md_edit(lchip, enable, version));
        CTC_ERROR_RETURN(_sys_usw_dtel_ifa_inband_hdr_edit(lchip, enable, version));
    }
    
    p_usw_dtel_master[lchip]->ifa_protocol = SYS_DTEL_IFA_PROTOCOL;
    p_usw_dtel_master[lchip]->ifa_en = enable;
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_ifa_set_mode_cfg(uint8 lchip, ctc_dtel_ifa_mode_cfg_t* p_mode_cfg)
{
    ParserLayer4AppCtl_m parser_int;
    DsIntSessionEdit_m int_edit;
    uint32 cmd = 0;
    uint16 req_vec = 0;
    uint8 probe_marker_mode = 0;
    uint8 loop = 0, md_len_sum = 0, metadata_len = 0, md_loop = 0;
    uint8 metadata_idx[2] = {0};
    uint8 req_vec_arr[CTC_DTEL_IFA_REQ_VEC_BIT_NUM] = {0};
    uint8 req_vec_arr_default[CTC_DTEL_IFA_REQ_VEC_BIT_NUM] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

    if(p_usw_dtel_master[lchip]->ifa_en)
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Do not support modify ifa mode config when IFA already enabled.\n");
        return CTC_E_IN_USE;
    }

    CTC_MAX_VALUE_CHECK(p_mode_cfg->version, SYS_DTEL_IFA_VER_MAX);

    cmd = DRV_IOR(ParserLayer4AppCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parser_int));
    probe_marker_mode = GetParserLayer4AppCtl(V, udpProbeIntEn_f, &parser_int);

    /*check requset vector*/
    for(loop = 0; loop < CTC_DTEL_IFA_REQ_VEC_BIT_NUM-1; ++loop)
    {
        CTC_MAX_VALUE_CHECK(p_mode_cfg->req_vec[loop], CTC_DTEL_IFA_REQ_VEC_LV2_PORT);
        if(p_mode_cfg->req_vec[loop] & (p_mode_cfg->req_vec[loop]-1))
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Please set ifa request vector according to ctc_dtel_ifa_request_vector_t enum.\n");
            return CTC_E_INVALID_PARAM;
        }
    }
    req_vec_arr[0] = SYS_DTEL_IFA_REQ_VEC_SW_ID;
    md_len_sum = 1;
    for(loop = 1; loop < CTC_DTEL_IFA_REQ_VEC_BIT_NUM; ++loop)
    {
        req_vec_arr[loop] = p_mode_cfg->req_vec[loop-1] ? p_mode_cfg->req_vec[loop-1]<<1 : req_vec_arr_default[loop];
        _sys_usw_dtel_ifa_mapping_metadata_idx(lchip, req_vec_arr[loop], metadata_idx, &metadata_len);
        md_len_sum += metadata_len;
        if(md_len_sum > SYS_DTEL_INT_MAX_METADATA_INDEX+1)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Exceed supported max metedata num limitation.\n");
            return CTC_E_INVALID_CONFIG;
        }
    }
    
    for(req_vec = 0; req_vec < (SYS_DTEL_IFA_SUPPORT_REQUEST_VECTOR+1); ++req_vec)
    {
        sal_memset(&int_edit, 0, sizeof(DsIntSessionEdit_m));
        
        SetDsIntSessionEdit(V, intProbeEn_f, &int_edit, probe_marker_mode);

        for(loop = 0, md_len_sum = 0; loop < CTC_DTEL_IFA_REQ_VEC_BIT_NUM; ++loop)
        {
            if (!CTC_IS_BIT_SET(req_vec, (CTC_DTEL_IFA_REQ_VEC_BIT_NUM-1-loop)))
            {
                continue;
            }
            _sys_usw_dtel_ifa_mapping_metadata_idx(lchip, req_vec_arr[loop], metadata_idx, &metadata_len);
            for (md_loop=0; md_loop<metadata_len; md_loop++)
            {
                SetDsIntSessionEdit(V, g_0_intMdataIdx_f + md_len_sum, &int_edit,  metadata_idx[md_loop]);
                md_len_sum++;
            }
        }
        
        SetDsIntSessionEdit(V, intMdNum_f, &int_edit, md_len_sum);
        cmd = DRV_IOW(DsIntSessionEdit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, req_vec, cmd, &int_edit));
    }
    /*ifa default version 2*/
    p_usw_dtel_master[lchip]->ifa_ver = p_mode_cfg->version ? p_mode_cfg->version : 2;
    SYS_CB(SYS_CB_ACL_SET_IFA_VER, lchip, p_usw_dtel_master[lchip]->ifa_ver);
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_set_property(uint8 lchip, ctc_dtel_property_t type, void* value)
{
    ctc_dtel_int_transmit_action_t  *p_action = NULL;
    sys_int_cam_action_t    sys_action;
    DsIntEditCtl_m epe_edit;
    IpeFwdIntCtl_m fwd_int;
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint8  cam_edit = 0;
    uint32  int_en = 0;
    IpeFwdReserved_m ipe_fwd_rsv;
    uint32 val_32 = 0;

    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_DTEL_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(value);

    p_action = (ctc_dtel_int_transmit_action_t*)value;
    if (type >= CTC_DTEL_INT_CBIT_NOT_EQ_ZERO_ACTION && type <= CTC_DTEL_INT_BELOW_REMAIN_HOP_ACTION)
    {
        CTC_MAX_VALUE_CHECK(p_action->session_id,CTC_DTEL_INT_SINK_SESSION_NUM-1);
        CTC_MAX_VALUE_CHECK(p_action->action,MAX_CTC_EXCP_TYPE-1);
        CTC_MAX_VALUE_CHECK(p_action->session_type,CTC_DTEL_INT_SESSION_TYPE_SOURCE_TRANSMIT);
    } else
    {
        field_val = *(uint32*)value;
    }
    sal_memset(&sys_action, 0, sizeof(sys_action));
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DTEL, SYS_WB_APPID_DTEL_SUBID_MASTER, 1);

    switch(type)
    {
    case CTC_DTEL_INT_MODE_CFG:
        CTC_ERROR_RETURN(_sys_usw_dtel_int_set_mode_cfg(lchip, (ctc_dtel_int_mode_cfg_t*)value));
        break;
    case CTC_DTEL_INT_EN:
        CTC_MAX_VALUE_CHECK(field_val, 1);
        if (p_usw_dtel_master[lchip]->ifa_en)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA is enabled. Cannot support INT.\n");
            return CTC_E_INVALID_CONFIG;
        }
        cmd = DRV_IOR(EpeHeaderEditCtl_t, EpeHeaderEditCtl_intEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &int_en));
        if ((field_val && int_en)
            || (!field_val && !int_en))
        {
            return CTC_E_NONE;
        }
        if((DRV_IS_TMM(lchip) && SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A) || (DRV_IS_AT(lchip)) || (DRV_IS_TMG(lchip)))
        {
            cmd = DRV_IOR(IpeFwdReserved_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_fwd_rsv));
            val_32 = GetIpeFwdReserved(V, reserved_f, &ipe_fwd_rsv);
            if (field_val)
            {
                CTC_BIT_SET(val_32, 4);
            }
            else
            {
                CTC_BIT_UNSET(val_32, 4);
            }
            SetIpeFwdReserved(V, reserved_f, &ipe_fwd_rsv, val_32);
            cmd = DRV_IOW(IpeFwdReserved_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_fwd_rsv));
        }
        _sys_usw_dtel_init_parser(lchip, field_val);
        _sys_usw_dtel_init_int_edit(lchip, field_val);
        _sys_usw_dtel_init_fwd(lchip, field_val);
        break;
    case  CTC_DTEL_INT_TS_GRAN:
        CTC_MAX_VALUE_CHECK(field_val, 3);
        cmd = DRV_IOW(EpePktProcTsMiscCtl_t, EpePktProcTsMiscCtl_tsGranularity_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
        break;
    case  CTC_DTEL_SWITCH_ID:
        cmd = DRV_IOR(DsIntEditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));
        SetDsIntEditCtl(V, switchInfo0_f, &epe_edit, field_val );
        SetDsIntEditCtl(V, switchInfo1_f, &epe_edit, field_val );
        cmd = DRV_IOW(DsIntEditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));
        p_usw_dtel_master[lchip]->switch_id = field_val;
        break;
    case   CTC_DTEL_INT_REP_LEN_THRD:
        CTC_MAX_VALUE_CHECK(field_val,CTC_MAX_UINT8_VALUE);
        cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
        SetIpeFwdIntCtl(V, intReportLenThreshold_f, &fwd_int, field_val);
        cmd = DRV_IOW(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
        break;
    case   CTC_DTEL_INT_SINK_LEN_THRD:
        CTC_MAX_VALUE_CHECK(field_val,CTC_MAX_UINT8_VALUE);
        cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
        SetIpeFwdIntCtl(V, intSinkLenThreshold_f, &fwd_int, field_val);
        cmd = DRV_IOW(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
        break;
    case  CTC_DTEL_INT_REMAINING_HOP_THRD:
        CTC_MAX_VALUE_CHECK(field_val,CTC_MAX_UINT8_VALUE);
        cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
        SetIpeFwdIntCtl(V, remainHopThreshold_f, &fwd_int,field_val);
        cmd = DRV_IOW(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
        break;
    case   CTC_DTEL_INT_LV2_PORT_MODE:
        CTC_MAX_VALUE_CHECK(field_val,CTC_DTEL_INT_LV2_PORT_MODE_INTERFACE);
        cmd = DRV_IOR(DsIntEditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));
        if (field_val == CTC_DTEL_INT_LV2_PORT_MODE_GPORT)
        {
            SetDsIntEditCtl(V, level2PortMode_f, &epe_edit, 0);
        }
        else  if(field_val== CTC_DTEL_INT_LV2_PORT_MODE_LOGIC_PORT)
        {
            SetDsIntEditCtl(V, level2PortMode_f, &epe_edit, 1);
        }
        else   if(field_val == CTC_DTEL_INT_LV2_PORT_MODE_INTERFACE)
        {
            SetDsIntEditCtl(V, level2PortMode_f, &epe_edit, 2);
        }
        cmd = DRV_IOW(DsIntEditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));
        break;

        /*the following cfg only occur on transmit node,the configured data is ctc_dtel_int_transmit_action_t*/
    case CTC_DTEL_INT_CBIT_NOT_EQ_ZERO_ACTION:    /**< [TMM]  C bit !=0 on transmit node */
        sys_action.cam_idx = SYS_INT_HDRCAM_IDX_CBIT_EQ_1;
        cam_edit = 1;
        break;
    case CTC_DTEL_INT_REP_NOT_EQ_ZERO_ACTION:     /**< [TMM] Rep bits !=0 on transmit node*/
        sys_action.session_type = p_action->session_type;
        sys_action.session_id = p_action->session_id;
        sys_action.to_cpu = p_action->action;
        sys_action.cam_idx = SYS_INT_HDRCAM_IDX_REPBIT_EQ_1;
        _sys_dtel_set_inthdr_cam(lchip, NULL, NULL, &sys_action);

        sys_action.cam_idx = SYS_INT_HDRCAM_IDX_REPBIT_EQ_2;
        cam_edit = 1;
        break;
    case  CTC_DTEL_INT_EXCEED_SINK_LEN_ACTION:      /**< [TMM]  the INT PKT's length exceed  CTC_DTEL_INT_SINK_LEN_THRESHOLD   */
        sys_action.cam_idx = SYS_INT_HDRCAM_IDX_EXCEED_SINK_LEN;
        cam_edit = 1;
        break;

    case  CTC_DTEL_INT_EXCEED_REP_LEN_ACTION:   /**< [TMM]  the INT PKT's length exceed  CTC_DTEL_INT_REPORT_LEN_THRESHOLD*/
        sys_action.cam_idx = SYS_INT_HDRCAM_IDX_EXCEED_REPORT_LEN;
        cam_edit = 1;
        break;
    case  CTC_DTEL_INT_BELOW_REMAIN_HOP_ACTION:   /**< [TMM] the INT PKT's Remaining Hop Cnt less than  CTC_DTEL_INT_REMAIN_HOP_THRESHOLD*/
        {
            sys_action.cam_idx = SYS_INT_HDRCAM_IDX_EXCEED_RHC;
            sys_action.session_type = p_action->session_type;
            sys_action.session_id = p_action->session_id;
            sys_action.to_cpu =   p_action->action;
            return _sys_dtel_set_inthdr_cam(lchip, NULL, NULL, &sys_action);
        }
        break;
    case CTC_DTEL_INT_REMAINING_HOP_CNT:
        CTC_VALUE_RANGE_CHECK(field_val, 1, 0xFF);
        field_val = 0;
        cmd = DRV_IOR(EpeHeaderEditCtl_t, EpeHeaderEditCtl_intEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
        if (!field_val)
        {
            return CTC_E_INVALID_CONFIG;
        }
        field_val = *(uint32*)value - 1;
        _sys_usw_dtel_int_set_remaining_hop_cnt(lchip, field_val);
        break;
    case CTC_DTEL_TSX_CFG:
        CTC_ERROR_RETURN(_sys_usw_dtel_tsx_set_cfg(lchip, (ctc_dtel_tsx_cfg_t*)value));
       break;
    case CTC_DTEL_TEX_CFG:
        CTC_ERROR_RETURN(_sys_usw_dtel_tex_set_cfg(lchip, (ctc_dtel_tex_cfg_t*)value));
        break;
    case CTC_DTEL_TIX_CFG:
        CTC_ERROR_RETURN(_sys_usw_dtel_tix_set_cfg(lchip, (ctc_dtel_tix_cfg_t*)value));
        break;
    case CTC_DTEL_IFA_EN:
        CTC_ERROR_RETURN(_sys_usw_dtel_set_ifa_en(lchip, field_val));
        break;
    case CTC_DTEL_IFA_PROTOCOL:
        {
        ParserIpCtl_m parserIp;

        if (!p_usw_dtel_master[lchip]->ifa_en)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not enabled.\n");
            return CTC_E_NOT_READY;
        }
        if (field_val > 0xFF)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Invalid IFA protocol.\n");
            return CTC_E_INVALID_CONFIG;
        }
        cmd = DRV_IOR(ParserIpCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parserIp));
        SetParserIpCtl(V, ipv4ExtHdr0Protocol_f, &parserIp, field_val);
        SetParserIpCtl(V, ipv6ExtHdr1Protocol_f, &parserIp, field_val);
        cmd = DRV_IOW(ParserIpCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &parserIp));
        p_usw_dtel_master[lchip]->ifa_protocol = field_val;
        }
        break;
    case CTC_DTEL_INT_TUNNEL_DEFAULT_SESSION_ID:
        CTC_MAX_VALUE_CHECK(field_val, CTC_DTEL_INT_SINK_SESSION_NUM - 1);
        cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
        SetIpeFwdIntCtl(V, tunnelDecapIntOpPtr_f, &fwd_int, field_val);
        cmd = DRV_IOW(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
        break;
    case CTC_DTEL_IFA_MODE_CFG:
        CTC_ERROR_RETURN(_sys_usw_dtel_ifa_set_mode_cfg(lchip, (ctc_dtel_ifa_mode_cfg_t*)value));
        break;
    default:
        break;
    }

    if (cam_edit)
    {
         sys_action.session_type = p_action->session_type;
         sys_action.session_id = p_action->session_id;
         sys_action.to_cpu =   p_action->action;
         _sys_dtel_set_inthdr_cam(lchip, NULL, NULL, &sys_action);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_get_property(uint8 lchip,ctc_dtel_property_t type,void *value)
{
    uint8   cam_edit = 0;
    uint32  cmd = 0;
    uint32  field_val = 0;
    uint32* p_data = (uint32*)value;
    ctc_dtel_int_transmit_action_t* p_action = (ctc_dtel_int_transmit_action_t*)value;
    sys_int_cam_action_t sys_action;
    DsIntEditCtl_m epe_edit;
    IpeFwdIntCtl_m fwd_int;

    sal_memset(&epe_edit, 0, sizeof(DsIntEditCtl_m));
    sal_memset(&fwd_int, 0, sizeof(IpeFwdIntCtl_m));
    sal_memset(&sys_action, 0, sizeof(sys_int_cam_action_t));
    switch(type)
    {
        case CTC_DTEL_INT_MODE_CFG:
        {
            CTC_ERROR_RETURN(_sys_usw_dtel_int_get_mode_cfg(lchip, (ctc_dtel_int_mode_cfg_t*)value));
            break;
        }
        case CTC_DTEL_INT_EN:
        {
            cmd = DRV_IOR(EpeHeaderEditCtl_t, EpeHeaderEditCtl_intEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
            *p_data = field_val;
            break;
        }
        case  CTC_DTEL_INT_TS_GRAN:
        {
            cmd = DRV_IOR(EpePktProcTsMiscCtl_t, EpePktProcTsMiscCtl_tsGranularity_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
            *p_data = field_val;
            break;
        }
        case CTC_DTEL_SWITCH_ID:
        {
            *p_data = p_usw_dtel_master[lchip]->switch_id;
            break;
        }
        case CTC_DTEL_INT_REP_LEN_THRD:
        {
            cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
            *p_data = GetIpeFwdIntCtl(V, intReportLenThreshold_f, &fwd_int);
            break;
        }
        case CTC_DTEL_INT_SINK_LEN_THRD:
        {
            cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
            *p_data = GetIpeFwdIntCtl(V, intSinkLenThreshold_f, &fwd_int);
            break;
        }
        case CTC_DTEL_INT_REMAINING_HOP_THRD:
        {
            cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
            *p_data = GetIpeFwdIntCtl(V, remainHopThreshold_f, &fwd_int);
            break;
        }
        case CTC_DTEL_INT_LV2_PORT_MODE:
        {
            cmd = DRV_IOR(DsIntEditCtl_t, DsIntEditCtl_level2PortMode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
            if (field_val == 0)
            {
                *p_data = CTC_DTEL_INT_LV2_PORT_MODE_GPORT;
            }
            else if (field_val == 1)
            {
                *p_data = CTC_DTEL_INT_LV2_PORT_MODE_LOGIC_PORT;
            }
            else if (field_val == 2)
            {
                *p_data = CTC_DTEL_INT_LV2_PORT_MODE_INTERFACE;
            }
            break;
        }

            /*the following cfg only occur on transmit node:*/
        case CTC_DTEL_INT_CBIT_NOT_EQ_ZERO_ACTION:
        {
            sys_action.cam_idx = SYS_INT_HDRCAM_IDX_CBIT_EQ_1;
            cam_edit = 1;
            break;
        }
        case CTC_DTEL_INT_REP_NOT_EQ_ZERO_ACTION:
        {
            sys_action.cam_idx = SYS_INT_HDRCAM_IDX_REPBIT_EQ_1;
            cam_edit = 1;
            break;
        }
        case CTC_DTEL_INT_EXCEED_SINK_LEN_ACTION:
        {
            sys_action.cam_idx = SYS_INT_HDRCAM_IDX_EXCEED_SINK_LEN;
            cam_edit = 1;
            break;
        }

        case CTC_DTEL_INT_EXCEED_REP_LEN_ACTION:
        {
            sys_action.cam_idx = SYS_INT_HDRCAM_IDX_EXCEED_REPORT_LEN;
            cam_edit = 1;
            break;
        }

        case CTC_DTEL_INT_BELOW_REMAIN_HOP_ACTION:
        {
            sys_action.cam_idx = SYS_INT_HDRCAM_IDX_EXCEED_RHC;
            cam_edit = 1;
            break;
        }

        case CTC_DTEL_INT_REMAINING_HOP_CNT:
        {
            DsIntSessionEdit_m int_edit;
            sys_int_hdr_t  int_header;

            cmd = DRV_IOR(EpeHeaderEditCtl_t, EpeHeaderEditCtl_intEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
            if (!field_val)
            {
                *p_data = 0;
                return CTC_E_NONE;
            }
            cmd = DRV_IOR(DsIntSessionEdit_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &int_edit));
            GetDsIntSessionEdit(A, intHeader_f, &int_edit, &int_header);
            *p_data = int_header.remaining_hop_cnt + 1;
             break;
        }

        case CTC_DTEL_TSX_CFG:
            CTC_ERROR_RETURN(_sys_usw_dtel_tsx_get_cfg(lchip, (ctc_dtel_tsx_cfg_t*)value));
           break;
        case CTC_DTEL_TEX_CFG:
            CTC_ERROR_RETURN(_sys_usw_dtel_tex_get_cfg(lchip, (ctc_dtel_tex_cfg_t*)value));
            break;
        case CTC_DTEL_TIX_CFG:
            CTC_ERROR_RETURN(_sys_usw_dtel_tix_get_cfg(lchip, (ctc_dtel_tix_cfg_t*)value));
            break;
        case CTC_DTEL_IFA_EN:
            *p_data = p_usw_dtel_master[lchip]->ifa_en;
            break;
        case CTC_DTEL_IFA_PROTOCOL:
            if (!p_usw_dtel_master[lchip]->ifa_en)
            {
                SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not enabled.\n");
                return CTC_E_NOT_READY;
            }
            *p_data = p_usw_dtel_master[lchip]->ifa_protocol;
            break;
        case CTC_DTEL_INT_TUNNEL_DEFAULT_SESSION_ID:
            cmd = DRV_IOR(IpeFwdIntCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fwd_int));
            *p_data = GetIpeFwdIntCtl(V, tunnelDecapIntOpPtr_f, &fwd_int);
            break;
        case CTC_DTEL_IFA_MODE_CFG:
            CTC_ERROR_RETURN(_sys_usw_dtel_ifa_get_mode_cfg(lchip, (ctc_dtel_ifa_mode_cfg_t*)value));
            break;
        default:
            break;
    }
    if (cam_edit)
    {
        _sys_dtel_get_inthdr_cam(lchip, &sys_action);
        p_action->session_id = sys_action.session_id;
        p_action->session_type = sys_action.session_type;
        p_action->action = sys_action.to_cpu;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_set_ifa_cfg(uint8 lchip, ctc_dtel_ifa_cfg_t *p_cfg)
{
    uint32 cmd = 0;
    uint32 random_thrd = 0;
    sys_nh_info_dsnh_t nhinfo;
    DsIntIgrSinkSession_m igs_session;
    DsIntEgrSinkSession_m egs_session;
    uint8 req_vec_num = 0;
    uint8 req_vec_bit = 0;

    if (!p_usw_dtel_master[lchip]->ifa_en || !p_usw_dtel_master[lchip]->ifa_session)
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not enabled.\n");
        return CTC_E_NOT_READY;
    }
    if ((CTC_DTEL_IFA_NODE_NONE != p_cfg->node)
        && (CTC_DTEL_IFA_NODE_NONE != p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].node)
        && (p_cfg->node != p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].node))
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "You should set session[%d] to none firstly.\n", p_cfg->session_id);
        return CTC_E_INVALID_CONFIG;
    }

    cmd = DRV_IOR(DsIntIgrSinkSession_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &igs_session));
    cmd = DRV_IOR(DsIntEgrSinkSession_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &egs_session));
    SetDsIntIgrSinkSession(V, egrSinkSessionId_f, &igs_session, p_cfg->session_id);
    SetDsIntIgrSinkSession(V, randomEn_f, &igs_session, 0);
    SetDsIntIgrSinkSession(V, logEn_f, &igs_session, 0);
    SetDsIntEgrSinkSession(V, logFollowIgr_f, &egs_session, 0);
    SetDsIntEgrSinkSession(V, logBlock_f, &egs_session, 7);    // ACL log 2
    switch (p_cfg->node)
    {
        case CTC_DTEL_IFA_NODE_NONE:
            SetDsIntEgrSinkSession(V, logEn_f, &egs_session, 0);
            SetDsIntEgrSinkSession(V, randomEn_f, &egs_session, 0);
            SetDsIntEgrSinkSession(V, randomThreshold_f, &egs_session, 0);
            sal_memset(&p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id], 0, sizeof(sys_dtel_ifa_session_t));
            break;
        case CTC_DTEL_IFA_NODE_INITIATOR:
            if (p_cfg->gns == SYS_DTEL_IFA_GNS_IS_LNS)
            {
                SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Not support LNS.\n");
                return CTC_E_NOT_SUPPORT;
            }
            CTC_MAX_VALUE_CHECK(p_cfg->gns, SYS_DTEL_IFA_MAX_GNS)
            if (p_cfg->req_vec & (~SYS_DTEL_IFA_REQ_VEC_ALL))
            {
                return CTC_E_INVALID_CONFIG;
            }
            do{
                if (p_cfg->req_vec & (1 << req_vec_bit))
                {
                    req_vec_num++;
                }
            }while (++req_vec_bit < 8);
            req_vec_num++;  /* for device id metdata len*/
            CTC_MIN_VALUE_CHECK((p_cfg->max_length ? p_cfg->max_length : SYS_DTEL_IFA_DEFAULT_MAX_LENGTH), req_vec_num);
            CTC_MAX_VALUE_CHECK(p_cfg->log_percent, CTC_LOG_PERCENT_MAX - 1);
            _sys_dtel_mapping_log_percent(lchip, p_cfg->log_percent, &random_thrd);
            SetDsIntEgrSinkSession(V, logId_f, &egs_session, 0);
            SetDsIntEgrSinkSession(V, logEn_f, &egs_session, 0);
            SetDsIntEgrSinkSession(V, randomEn_f, &egs_session, 1);
            SetDsIntEgrSinkSession(V, randomThreshold_f, &egs_session, random_thrd);
            p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].gns = p_cfg->gns;
            p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].max_length = p_cfg->max_length ? p_cfg->max_length : SYS_DTEL_IFA_DEFAULT_MAX_LENGTH;
            p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].hop_limit = p_cfg->hop_limit ? p_cfg->hop_limit : SYS_DTEL_IFA_DEFAULT_HOP_LIMIT;
            p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].req_vec = p_cfg->req_vec;
            break;
        case CTC_DTEL_IFA_NODE_TRANSIT:
            SetDsIntEgrSinkSession(V, logId_f, &egs_session, 1);
            SetDsIntEgrSinkSession(V, logEn_f, &egs_session, 1);
            SetDsIntEgrSinkSession(V, randomEn_f, &egs_session, 0);
            SetDsIntEgrSinkSession(V, randomThreshold_f, &egs_session, 0);
            /*Egress session config discard IFA packet*/
            SetDsIntEgrSinkSession(V, discard_f, &egs_session, 1);
            SetDsIntEgrSinkSession(V, discardType_f, &egs_session, SYS_DTEL_INT_EPE_DISCARDTYPE);
            break;
        case CTC_DTEL_IFA_NODE_TERMINATE:
            if (p_usw_dtel_master[lchip]->ifa_eunit_en && 0 == p_cfg->nh_id)
            {
                SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA eunit enabled, nh_id must not equal 0.\n");
                return CTC_E_INVALID_PARAM;
            }
            SetDsIntEgrSinkSession(V, logId_f, &egs_session, 2);
            SetDsIntEgrSinkSession(V, logEn_f, &egs_session, 1);
            SetDsIntEgrSinkSession(V, randomEn_f, &egs_session, 0);
            SetDsIntEgrSinkSession(V, randomThreshold_f, &egs_session, 0);
            /*Egress session config discard IFA packet*/
            SetDsIntEgrSinkSession(V, discard_f, &egs_session, 1);
            SetDsIntEgrSinkSession(V, discardType_f, &egs_session, SYS_DTEL_INT_EPE_DISCARDTYPE);

            if (p_cfg->nh_id)
            {
                sal_memset(&nhinfo, 0, sizeof(sys_nh_info_dsnh_t));
                CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_cfg->nh_id, &nhinfo, 0));
            }
            p_usw_dtel_master[lchip]->nhid[p_cfg->session_id] = p_cfg->nh_id;
            break;
        default:
            break;
    }
    p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].node = p_cfg->node;

    cmd = DRV_IOW(DsIntIgrSinkSession_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &igs_session));
    cmd = DRV_IOW(DsIntEgrSinkSession_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &egs_session));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_get_ifa_cfg(uint8 lchip, ctc_dtel_ifa_cfg_t *p_cfg)
{
    if (!p_usw_dtel_master[lchip]->ifa_en || !p_usw_dtel_master[lchip]->ifa_session)
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not enabled.\n");
        return CTC_E_NOT_READY;
    }
    p_cfg->node = p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].node;
    switch (p_cfg->node)
    {
        case CTC_DTEL_IFA_NODE_INITIATOR:
            {
                DsIntEgrSinkSession_m egs_session;
                uint32 random_thrd = 0;
                uint32 cmd = DRV_IOR(DsIntEgrSinkSession_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_cfg->session_id, cmd, &egs_session));
                random_thrd = GetDsIntEgrSinkSession(V, randomThreshold_f, &egs_session);
                _sys_dtel_unmapping_log_percent(lchip, random_thrd, &p_cfg->log_percent);
                p_cfg->gns = p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].gns;
                p_cfg->max_length = p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].max_length;
                p_cfg->hop_limit = p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].hop_limit;
                p_cfg->req_vec = p_usw_dtel_master[lchip]->ifa_session[p_cfg->session_id].req_vec;
            }
            break;
        case CTC_DTEL_IFA_NODE_TERMINATE:
            p_cfg->nh_id = p_usw_dtel_master[lchip]->nhid[p_cfg->session_id];
            break;
        default:
            break;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_dtel_int_pkt_decode(uint8 lchip, ctc_pkt_rx_t* p_pkt_rx, sys_int_pkt_info_t* int_pkt_info)
{
#if defined(TSINGMA_MX) || defined(TSINGMA_GX)
    uint8* p_hdr = NULL;
    ctc_pkt_info_t* p_rx_info      = NULL;
    ms_packet_header_tmm_tail_t* p_raw_hdr_tail = NULL;
    uint16 lantency_20_31 = 0;
    ms_packet_header_tmm_t* p_raw_hdr = NULL;

    /* 1. check packet length */
    /* ethernet has 20 Bytes L2 header */
    p_hdr = p_pkt_rx->pkt_buf[0].data;
    if (CTC_PKT_MODE_ETH == p_pkt_rx->mode)
    {
        p_hdr += SYS_USW_PKT_CPUMAC_LEN;
    }

    /* 2. decode raw header */
    p_rx_info = &p_pkt_rx->rx_info;
    sys_usw_swap32((uint32*)p_hdr, SYS_USW_PKT_HEADER_LEN / sizeof(uint32), FALSE);

    p_raw_hdr = (ms_packet_header_tmm_t*)p_hdr;
    p_raw_hdr_tail = (ms_packet_header_tmm_tail_t*)((uint32*)p_raw_hdr + 10);
    int_pkt_info->igs_timestamp    = p_raw_hdr->timestamp_36_5_29_0 | (p_raw_hdr->timestamp_36_5_31_30 << 30);
    int_pkt_info->local_src_port   = p_raw_hdr->u1.intdata.src_local_phy_port_9_7_0 | ((p_raw_hdr->u1_data & 0x1) << 8);

    int_pkt_info->queue_id         = p_raw_hdr->fid & 0x7; /*now support 8 sub queue, grpoffset = 0 */
    int_pkt_info->queue_cnt        = p_raw_hdr->u1.intdata.queue_depth_16_11_0 | (p_raw_hdr->u1.intdata.queue_depth_16_15_12 << 12);
    lantency_20_31                   = p_raw_hdr->src_svlan_id;
    int_pkt_info->hop_lantency     = (lantency_20_31 << 20) + p_raw_hdr->u1.intdata.latency;
    int_pkt_info->egs_port_load    = p_raw_hdr->u1.intdata.int_dest_port_load;
    int_pkt_info->local_dst_port   = p_rx_info->lport;

    if (p_pkt_rx->rx_info.oper_type == CTC_PKT_OPER_INT)
    {
        uint8  log_id = 0;

        int_pkt_info->int_session = p_raw_hdr->ttl;
        int_pkt_info->int_session &= 0x1F;
        /*Get Log ID*/
        for (log_id = 0; (log_id < SYS_DTEL_INT_LOG_ID_NUM) && !p_usw_dtel_master[lchip]->ifa_en; log_id++)
        {
            if (CTC_BMP_ISSET(p_usw_dtel_master[lchip]->log_en[log_id], int_pkt_info->int_session))
            {
                int_pkt_info->is_postcard = CTC_IS_BIT_SET(p_usw_dtel_master[lchip]->postcard_en, log_id);
                break;
            }
        }
    }
    else
    {
        if((DRV_IS_TMM(lchip) && SYS_GET_CHIP_VERSION == SYS_CHIP_SUB_VERSION_A) || DRV_IS_TMG(lchip))
        {
            int_pkt_info->int_session      = p_raw_hdr_tail->int_and_sr_shared;
            int_pkt_info->int_session      = (int_pkt_info->int_session >> 2) & 0x1F;
        }
        else
        {
            int_pkt_info->int_session      =  p_raw_hdr->u1.normal.bypass_cflex_src_check;
            int_pkt_info->int_session      |=  ((p_raw_hdr->u1.normal.cflex_fwd_sg_group_sel_3_1_0 <<1) | (p_raw_hdr->u1_data&0x1)<<3);
            int_pkt_info->int_session      |= (p_raw_hdr->u1.normal.truncate_len_prof_id<<4);
            int_pkt_info->int_session      &= 0x1F;
        }
    }
#endif
    return CTC_E_NONE;
}


STATIC int32
_sys_at_dtel_int_pkt_decode(uint8 lchip, ctc_pkt_rx_t* p_pkt_rx, sys_int_pkt_info_t* int_pkt_info)
{
#ifdef ARCTIC
    uint8* p_hdr = NULL;
    ctc_pkt_info_t* p_rx_info      = NULL;
    ms_packet_header_tail_at_t* p_raw_hdr_tail = NULL;
    uint16 lantency_20_31 = 0;
    ms_packet_header_at_t* p_raw_hdr = NULL;

    /* 1. check packet length */
    /* ethernet has 20 Bytes L2 header */
    p_hdr = p_pkt_rx->pkt_buf[0].data;
    if (CTC_PKT_MODE_ETH == p_pkt_rx->mode)
    {
        p_hdr += SYS_USW_PKT_CPUMAC_LEN;
    }

    /* 2. decode raw header */
    p_rx_info = &p_pkt_rx->rx_info;
#if (1 == SDK_WORK_PLATFORM)
    sys_usw_swap32((uint32*)p_hdr, SYS_USW_PKT_HEADER_LEN / sizeof(uint32), FALSE);
#endif
    p_raw_hdr = (ms_packet_header_at_t*)p_hdr;
    p_raw_hdr_tail = (ms_packet_header_tail_at_t*)((uint32*)p_raw_hdr + 10);
    int_pkt_info->igs_timestamp    = p_raw_hdr->timestamp_36_5_29_0 | (p_raw_hdr->timestamp_36_5_31_30 << 30);
    int_pkt_info->local_src_port   = p_raw_hdr->u1.intdata.src_local_phy_port_9_7_0 | ((p_raw_hdr->u1_data & 0x1) << 8);
    int_pkt_info->queue_id         = p_raw_hdr->fid & 0x7; /*now support 8 sub queue, grpoffset = 0 */
    int_pkt_info->queue_cnt        = p_raw_hdr->u1.intdata.queue_depth_16_11_0 | (p_raw_hdr->u1.intdata.queue_depth_16_15_12 << 12);
    lantency_20_31                   = p_raw_hdr->src_svlan_id;
    int_pkt_info->hop_lantency     = (lantency_20_31 << 20) + p_raw_hdr->u1.intdata.latency;
    int_pkt_info->egs_port_load    = p_raw_hdr->u1.intdata.int_dest_port_load;
    int_pkt_info->local_dst_port   = p_rx_info->lport;

    if (p_pkt_rx->rx_info.oper_type == CTC_PKT_OPER_INT)
    {
        uint8  log_id = 0;

        int_pkt_info->int_session = p_raw_hdr->ttl;
        int_pkt_info->int_session &= 0x1F;
        /*Get Log ID*/
        for (log_id = 0; (log_id < SYS_DTEL_INT_LOG_ID_NUM) && !p_usw_dtel_master[lchip]->ifa_en; log_id++)
        {
            if (CTC_BMP_ISSET(p_usw_dtel_master[lchip]->log_en[log_id], int_pkt_info->int_session))
            {
                int_pkt_info->is_postcard = CTC_IS_BIT_SET(p_usw_dtel_master[lchip]->postcard_en, log_id);
                break;
            }
        }
    }
    else
    {
        int_pkt_info->int_session      = p_raw_hdr_tail->u.cpu.int_and_sr_shared;
        int_pkt_info->int_session      = (int_pkt_info->int_session >> 2) & 0x1F;
    }
#endif
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_dtel_int_pkt_rx(ctc_pkt_rx_t* p_pkt_rx)
{
    int32  ret = CTC_E_NONE;
    uint8  from_ipe = 0;
    uint8 lchip = p_pkt_rx->lchip;
    uint8  illegal_report = 0;
    sys_dtel_pkt_t* p_int_pkt = NULL;
    sys_dtel_pkt_t temp_int_pkt;
    sys_int_pkt_info_t int_pkt_info;

    sal_memset(&int_pkt_info, 0, sizeof(sys_int_pkt_info_t));

    from_ipe = (p_pkt_rx->rx_info.oper_type == CTC_PKT_OPER_INT? 0: 1);
    (*p_usw_dtel_master[lchip]->g_sys_dtel_int_pkt_decode_cb)(lchip, p_pkt_rx, &int_pkt_info);
    p_usw_dtel_master[lchip]->log_cnt[from_ipe? CTC_INGRESS : CTC_EGRESS]++;
    if (!int_pkt_info.is_postcard)     /*INT in-band mode*/
    {
        temp_int_pkt.igs_ts = int_pkt_info.igs_timestamp;
        temp_int_pkt.local_src_port = from_ipe? p_pkt_rx->rx_info.lport : int_pkt_info.local_src_port;
        temp_int_pkt.hash = p_pkt_rx->rx_info.hash;
        p_int_pkt = ctc_hash_lookup(p_usw_dtel_master[lchip]->int_rep_info, (void*)&temp_int_pkt);
        if (p_int_pkt)  /*update*/
        {
            if (SYS_DTEL_REP_MODE_DONE == p_int_pkt->mode)
            {
                return CTC_E_NONE;
            }
            illegal_report = (SYS_DTEL_REP_MODE_NONE == p_int_pkt->mode? 1: 0);     /*sw error*/
            illegal_report = illegal_report || ((SYS_DTEL_REP_MODE_IPE == p_int_pkt->mode) && from_ipe? 1: 0);  /*rep pkt error*/
            illegal_report = illegal_report || ((SYS_DTEL_REP_MODE_EPE == p_int_pkt->mode) && !from_ipe? 1: 0); /*rep pkt error*/
            if (illegal_report)
            {
                CTC_ERROR_RETURN(CTC_E_INVALID_CONFIG);
            }
        }
    }
    int_pkt_info.from_ipe = from_ipe;
    CTC_ERROR_RETURN(_sys_usw_dtel_add_rep_hash(lchip, &int_pkt_info, p_pkt_rx, p_int_pkt));
    sal_sem_give(p_usw_dtel_master[lchip]->sink_sem);

    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " ReportMode:%s op:%s \n igs_ts:0x%x,local_src_port:%d,hash:%d\n",
                                                                    int_pkt_info.is_postcard ? "postcard" : "inband",
                                                                    p_int_pkt ? "update" : "add",
                                                                    temp_int_pkt.igs_ts, temp_int_pkt.local_src_port, temp_int_pkt.hash);
    return ret;
}


int32
sys_usw_dtel_show_int_status(uint8 lchip)
{
    uint32 i = 0;
    uint8 flag = 0;
    SYS_DTEL_INIT_CHECK(lchip);
    SYS_DTEL_LOCK(lchip);

    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "==================== %22s ====================\n", "Dtel Status:");
    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-34s:  0x%x\n",   "igs log cnt", p_usw_dtel_master[lchip]->log_cnt[CTC_INGRESS]);
    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-34s:  0x%x\n",   "egs log cnt", p_usw_dtel_master[lchip]->log_cnt[CTC_EGRESS]);
    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-34s:  0x%x\n",   "rep cnt", p_usw_dtel_master[lchip]->rep_id);

#define SYS_DTEL_PRINT_INT_LOG(S, BMP)\
    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-34s:  ",  S);\
    flag = 0;\
    for (i = 0; i < SYS_DTEL_INT_LOG_ID_NUM; i++)\
    {\
        if (!CTC_IS_BIT_SET((BMP), i)) {continue;}\
        if (flag) { SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, ",");}\
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%u", i);\
        flag = 1;\
    }\
    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    SYS_DTEL_PRINT_INT_LOG("inband logId", p_usw_dtel_master[lchip]->inband_en);
    SYS_DTEL_PRINT_INT_LOG("postcard logId", p_usw_dtel_master[lchip]->postcard_en);
    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "================================================================\n");

    SYS_DTEL_UNLOCK(lchip);
    return CTC_E_NONE;
}

#define SYS_IFA_PACK(N, V, L) \
do { \
    sal_memcpy(N, V, (L)); \
    N += (L); \
} while (0)

#define SYS_IFA_UNPACK(V, N, L, LN) \
do { \
    sal_memcpy((V), N, (L)); \
    N += (L); \
    LN += (L);\
} while (0)

#define SYS_IFA_UNPACK_EMPTY(N, L, LN)   N += (L); LN += (L);

#if (HOST_IS_LE == 1)
#define SYS_IFA_CONVERT_U16(DST, SRC)\
        DST = (((SRC) & 0xFF) << 8) | (((SRC) >> 8) & 0xFF);
#else
#define SYS_IFA_CONVERT_U16(DST, SRC)
#endif

#if (HOST_IS_LE == 1)
#define SYS_IFA_CONVERT_U32(DST, SRC)\
    DST = (((SRC) & 0xFF) << 24) | ((((SRC) >> 8) & 0xFF) << 16) | ((((SRC) >> 16) & 0xFF) << 8) | (((SRC) >> 24) & 0xFF);
#else
#define SYS_IFA_CONVERT_U32(DST, SRC)
#endif

#define SYS_IFA_UNPACK_LEN_CHK(LN, TO_LEN)   \
    if (LN >= TO_LEN) { return CTC_E_INVALID_MAX_FRAMESIZE;}\

STATIC uint16
_sys_usw_dtel_ifa_calc_ipv4_chksum(uint8* hdr, uint8 len)
{
    uint8 i = 0;
    uint16 value = 0;
    uint32 checksum=0;
    
    for(i = 0; i < len/2; i++)
    {
        value = (i == 5) ? 0 : ((hdr[i * 2] << 8) | hdr[i * 2 + 1]); /* jump old checksum*/
        checksum += value;
    }
    checksum = (checksum >> 16) + (checksum & 0xffff);
    checksum += (checksum >> 16);
    checksum = 0xffff - checksum;
    return (checksum & 0xffff);
}

#define SYS_DTEL_IFA_ENCODE_TCP_UDP \
            l4_hdr_ptr = r_pn;\
            if (6 == protocol) /*TCP*/\
            {\
                SYS_IFA_PACK(r_pn, pn, 12); \
                SYS_IFA_UNPACK_EMPTY(pn, 12, len); \
                SYS_IFA_PACK(r_pn, pn, 1); \
                SYS_IFA_UNPACK(&val_u8, pn, 1, len); \
                val_u8 = (val_u8 >> 4) * 4;/*unpack TCP data offset*/  \
                SYS_IFA_PACK(r_pn, pn, val_u8 - 13); \
                SYS_IFA_UNPACK_EMPTY(pn, val_u8 - 13, len); \
            } \
            else if (17 == protocol)/*UDP*/ \
            { \
                SYS_IFA_PACK(r_pn, pn, 8); \
                SYS_IFA_UNPACK_EMPTY(pn, 8, len); \
            }
/*
      IFA Header:
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      | Ver=2 |  GNS  |NextHdr = IP_xx|R|R|R|M|T|I|T|C|   Max Length  |
      |       |       |               | | | |F|S| |A| |               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



      The IFA metadata header is always present:
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      | Request Vector| Action Vector |   Hop Limit   | Current Length|
      |               |L|C|R|R|R|R|R|R|               |               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

*/

STATIC int32
_sys_usw_dtel_ifa_pkt_process(uint8 lchip, sys_int_pkt_info_t* p_info, uint8* pkt, uint16 pkt_len, uint8** r_pkt, uint16* r_pkt_len)
{
    uint8* pn = pkt;
    uint8* r_pn = *r_pkt;
    uint32 len = 0;
    uint8 protocol = 0;
    uint8 val_u8 = 0;
    uint16 val_u16 = 0;
    uint32 val_u32 = 0;
    uint8 hdr_len = 0;
    uint8 ii = 0;
    uint8 req_vec_num = 0;
    uint8 node = p_usw_dtel_master[lchip]->ifa_session[p_info->int_session].node;
    uint8 req_vec = 0;
    uint8 max_len = 0;
    uint8* hdr_ptr;
    uint8* l4_hdr_ptr;
    uint16 eth_type = 0;

    /*pack macda & macsa*/
    SYS_IFA_PACK(r_pn, pn, 12);
    SYS_IFA_UNPACK_EMPTY(pn, 12, len);

    do
    {
        /*unpack ether type*/
        SYS_IFA_PACK(r_pn, pn, 2);
        SYS_IFA_UNPACK(&eth_type, pn, 2, len);
        SYS_IFA_CONVERT_U16(eth_type, eth_type)
        SYS_IFA_UNPACK_LEN_CHK(len, pkt_len);
        if (0x0800 == eth_type || 0x86dd == eth_type)
        {
            break;
        }
        /*jump 2B vlan tag */
        SYS_IFA_PACK(r_pn, pn, 2);
        SYS_IFA_UNPACK_EMPTY(pn, 2, len);
    }while (1);

    if (CTC_DTEL_IFA_NODE_INITIATOR == node)
    {
        req_vec = p_usw_dtel_master[lchip]->ifa_session[p_info->int_session].req_vec;
        do{
            if (req_vec & (1 << ii))
            {
                req_vec_num++;
            }
        }while (++ii < 8);
    }

    hdr_ptr = r_pn;

    if (0x0800 == eth_type)/*ipv4*/
    {
        /*support ipv4 with option field*/
        SYS_IFA_PACK(r_pn, pn, 1);
        SYS_IFA_UNPACK(&val_u8, pn, 1, len);

        hdr_len = val_u8 & 0xF;/*IHL Get*/
        SYS_IFA_PACK(r_pn, pn, 8);
        SYS_IFA_UNPACK_EMPTY(pn, 8, len);


        if (CTC_DTEL_IFA_NODE_INITIATOR == node)
        {
            /*Parser Protocol*/
            SYS_IFA_PACK(r_pn, &p_usw_dtel_master[lchip]->ifa_protocol, 1);
            SYS_IFA_UNPACK(&protocol, pn, 1, len);

            if (protocol && 17 != protocol && 6 != protocol)
            {
                /*only support TCP&UDP*/
                SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not support protocol %d.\n", protocol);
                return CTC_E_NOT_SUPPORT;
            }

            SYS_IFA_PACK(r_pn, pn, hdr_len * 4 - 10);
            SYS_IFA_UNPACK_EMPTY(pn, hdr_len * 4 - 10, len);
        }
        else
        {
            /*Parser Protocol*/
            SYS_IFA_PACK(r_pn, pn, 1);
            SYS_IFA_UNPACK(&protocol, pn, 1, len);
            if (protocol != p_usw_dtel_master[lchip]->ifa_protocol)/* IFA Protocol Check */
            {
                SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA node %d, packet protocol(%d) is not equal to IFA protocol(%d).\n",
                                                        node, protocol, p_usw_dtel_master[lchip]->ifa_protocol);
                return CTC_E_INVALID_CONFIG;
            }
            SYS_IFA_PACK(r_pn, pn, hdr_len * 4 - 10);
            SYS_IFA_UNPACK_EMPTY(pn, hdr_len * 4 - 10, len);
        }
    }
    else/*ipv6*/
    {
        uint16 payload_len = 0;
        hdr_len = SYS_DTEL_IPV6_HEADER_LEN;

        SYS_IFA_PACK(r_pn, pn, 4);
        SYS_IFA_UNPACK_EMPTY(pn, 4, len);

        SYS_IFA_PACK(r_pn, pn, 2);
        SYS_IFA_UNPACK(&payload_len, pn, 2, len);
        SYS_IFA_CONVERT_U16(payload_len, payload_len)

        if (CTC_DTEL_IFA_NODE_INITIATOR == node)
        {
            /*Parser Protocol*/
            SYS_IFA_PACK(r_pn, &p_usw_dtel_master[lchip]->ifa_protocol, 1);
            SYS_IFA_UNPACK(&protocol, pn, 1, len);
            if (protocol && 17 != protocol && 6 != protocol)
            {
                /*only support TCP&UDP*/
                SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not support protocol %d.\n", protocol);
                return CTC_E_NOT_SUPPORT;
            }
        }
        else
        {
            SYS_IFA_PACK(r_pn, pn, 1);
            SYS_IFA_UNPACK(&protocol, pn, 1, len);
            if (protocol != p_usw_dtel_master[lchip]->ifa_protocol)/* IFA Protocol Check */
            {
                SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA node %d, packet protocol(%d) is not equal to IFA protocol(%d).\n",
                                                        node, protocol, p_usw_dtel_master[lchip]->ifa_protocol);
                return CTC_E_INVALID_CONFIG;
            }
        }
        SYS_IFA_PACK(r_pn, pn, hdr_len - 7);
        SYS_IFA_UNPACK_EMPTY(pn, hdr_len - 7, len);
    }

    if (CTC_DTEL_IFA_NODE_INITIATOR == node)
    {
        /*pack IFA header*/
        val_u8 = (SYS_DTEL_IFA_VER << 4) | (p_usw_dtel_master[lchip]->ifa_session[p_info->int_session].gns & 0xF);
        SYS_IFA_PACK(r_pn, &val_u8, 1);
        SYS_IFA_PACK(r_pn, &protocol, 1);
        val_u8 = 0;/*TODO: flags support*/
        SYS_IFA_PACK(r_pn, &val_u8, 1);
        val_u8 = p_usw_dtel_master[lchip]->ifa_session[p_info->int_session].max_length;
        SYS_IFA_PACK(r_pn, &val_u8, 1);
        SYS_DTEL_IFA_ENCODE_TCP_UDP;
        /*pack IFA metadata header*/
        SYS_IFA_PACK(r_pn, &req_vec, 1);
        val_u8 = 0;/*TODO: action vector support*/
        SYS_IFA_PACK(r_pn, &val_u8, 1);
        SYS_IFA_PACK(r_pn, &p_usw_dtel_master[lchip]->ifa_session[p_info->int_session].hop_limit, 1);
        val_u8 = req_vec_num + 1;
        SYS_IFA_PACK(r_pn, &val_u8, 1);
    }
    else
    {
        /*unpack IFA header*/
        SYS_IFA_PACK(r_pn, pn, 1);
        SYS_IFA_UNPACK(&val_u8, pn, 1, len);
        if (((val_u8 >> 4) & 0xF) != SYS_DTEL_IFA_VER)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not support IFA version %d.\n", (val_u8 >> 4) & 0xF);
            return CTC_E_NOT_SUPPORT;
        }
        /*unpack next_protocol*/
        SYS_IFA_PACK(r_pn, pn, 1);
        SYS_IFA_UNPACK(&protocol, pn, 1, len);
        if (protocol && 17 != protocol && 6 != protocol)
        {
            /*only support TCP&UDP*/
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not support protocol %d.\n", protocol);
            return CTC_E_NOT_SUPPORT;
        }
        SYS_IFA_PACK(r_pn, pn, 1);
        SYS_IFA_UNPACK(&val_u8, pn, 1, len);/*Flags*/
        if (val_u8)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not support flags 0x%x.\n", val_u8);
            return CTC_E_NOT_SUPPORT;
        }
        SYS_IFA_PACK(r_pn, pn, 1);
        SYS_IFA_UNPACK(&max_len, pn, 1, len);/*MAX Length*/

        SYS_DTEL_IFA_ENCODE_TCP_UDP;
        /*unpack IFA metadata header*/
        SYS_IFA_PACK(r_pn, pn, 1);
        SYS_IFA_UNPACK(&req_vec, pn, 1, len);
        SYS_IFA_PACK(r_pn, pn, 1);
        SYS_IFA_UNPACK(&val_u8, pn, 1, len); /*request vector*/
        if (val_u8)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA not support request vector 0x%x.\n", val_u8);
            return CTC_E_NOT_SUPPORT;
        }

        SYS_IFA_UNPACK(&val_u8, pn, 1, len); /*hop limit*/
        if (0 == val_u8)
        {
            /*If the incoming hop limit is 0, current nodes MUST NOT insert metadata.*/
            SYS_IFA_PACK(r_pn, &val_u8, 1);
            SYS_IFA_PACK(r_pn, pn, pkt_len - len- SYS_USW_DTEL_CRC_LEN);
            *r_pkt_len = r_pn - *r_pkt;
            return CTC_E_NONE;
        }
        else if (0xFF != val_u8)
        {
            val_u8 -= 1;
        }
        SYS_IFA_PACK(r_pn, &val_u8, 1);
        ii = 0;
        do{
            if (req_vec & (1 << ii))
            {
                req_vec_num++;
            }
        }while (++ii < 8);
        req_vec_num++;  /* for device id metdata len*/

        SYS_IFA_UNPACK(&val_u8, pn, 1, len); /*current length*/
        val_u8 += req_vec_num;
        if (val_u8 > max_len)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA metadata cur_length(%d) exceed max_len(%d).\n", val_u8, max_len);
            return CTC_E_EXCEED_MAX_SIZE;
        }
        SYS_IFA_PACK(r_pn, &val_u8, 1);
    }
    /*pack IFA metadata*/
    val_u32 = p_usw_dtel_master[lchip]->switch_id;
    SYS_IFA_CONVERT_U32(val_u32, val_u32)
    SYS_IFA_PACK(r_pn, &val_u32, 4);

    if (req_vec & CTC_DTEL_IFA_REQ_VEC_LV1_PORT)
    {
        val_u32 = p_info->local_src_port;
        val_u32 <<= 16;
        val_u32 |= p_info->local_dst_port;
        SYS_IFA_CONVERT_U32(val_u32, val_u32)
        SYS_IFA_PACK(r_pn, &val_u32, 4);
    }
    if (req_vec & CTC_DTEL_IFA_REQ_VEC_HOP_LATENCY)
    {
        val_u32 = p_info->hop_lantency;
        SYS_IFA_CONVERT_U32(val_u32, val_u32)
        SYS_IFA_PACK(r_pn, &val_u32, 4);
    }
    if (req_vec & CTC_DTEL_IFA_REQ_VEC_QUEUE_INFO)
    {
        val_u32 = p_info->queue_id;
        val_u32 <<= 24;
        val_u32 |= (p_info->queue_cnt & 0xFFFFFF);
        SYS_IFA_CONVERT_U32(val_u32, val_u32)
        SYS_IFA_PACK(r_pn, &val_u32, 4);
    }
    if (req_vec & CTC_DTEL_IFA_REQ_VEC_IGS_TS)
    {
        val_u32 = p_info->igs_timestamp;
        SYS_IFA_CONVERT_U32(val_u32, val_u32)
        SYS_IFA_PACK(r_pn, &val_u32, 4);
    }
    if (req_vec & CTC_DTEL_IFA_REQ_VEC_EGS_TS)
    {
        val_u32 = p_info->igs_timestamp + p_info->hop_lantency;
        SYS_IFA_CONVERT_U32(val_u32, val_u32)
        SYS_IFA_PACK(r_pn, &val_u32, 4);
    }
    if (req_vec & CTC_DTEL_IFA_REQ_VEC_EPTU)
    {
        val_u32 = p_info->egs_port_load;
        SYS_IFA_CONVERT_U32(val_u32, val_u32)
        SYS_IFA_PACK(r_pn, &val_u32, 4);
    }
    /*packet payload*/
    SYS_IFA_PACK(r_pn, pn, pkt_len - len -SYS_USW_DTEL_CRC_LEN);

    /*update  header length */
    if (0x0800 == eth_type)
    {
        /*update total_length*/
        val_u16 = r_pn - hdr_ptr;
        *(hdr_ptr + 2) = val_u16 >> 8;
        *(hdr_ptr + 3) = val_u16 & 0xFF;

        /*update checksum*/
        val_u16 = _sys_usw_dtel_ifa_calc_ipv4_chksum(hdr_ptr, hdr_len * 4);
        *(hdr_ptr + 10) = val_u16 >> 8;
        *(hdr_ptr + 11) = val_u16 & 0xFF;
    }
    else
    {
        /*update total_length*/
        val_u16 = r_pn - hdr_ptr;
        val_u16 -= 40;
        *(hdr_ptr + 4) = val_u16 >> 8;
        *(hdr_ptr + 5) = val_u16 & 0xFF;
    }

    /*update L4 header len and checksum*/
    if(17 == protocol)
    {
        /*update udp length*/
        val_u16 = r_pn - l4_hdr_ptr;
        *(l4_hdr_ptr + 4) = val_u16 >> 8;
        *(l4_hdr_ptr + 5) = val_u16 & 0xFF;
        /*checksum always 0*/
        *(l4_hdr_ptr + 6) = 0;
        *(l4_hdr_ptr + 7) = 0;
    }
    else
    {
        /*checksum always 0*/
        *(l4_hdr_ptr + 16) = 0;
        *(l4_hdr_ptr + 17) = 0;
    }
    *r_pkt_len = r_pn - *r_pkt;
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_dtel_ifa_pkt_rx(ctc_pkt_rx_t* p_pkt_rx)
{
    uint8 gchip = 0;
    uint8 lchip = p_pkt_rx->lchip;
    int32  ret = CTC_E_NONE;
    uint16 pkt_len = 0;
    uint16 rep_pkt_len = 0;
    uint8* rep_pkt = NULL;
    ctc_pkt_tx_t* pkt_tx = NULL;
    sys_int_pkt_info_t int_pkt_info;

    if (CTC_PARSER_PKT_TYPE_ETHERNET != p_pkt_rx->rx_info.packet_type
        && CTC_PARSER_PKT_TYPE_IP_OR_IPV6 != p_pkt_rx->rx_info.packet_type
        && CTC_PARSER_PKT_TYPE_IPV6 != p_pkt_rx->rx_info.packet_type)
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA Not Support Packet Type %d.\n", p_pkt_rx->rx_info.packet_type);
        return CTC_E_NOT_SUPPORT;
    }
    pkt_len = p_pkt_rx->pkt_len - p_pkt_rx->eth_hdr_len - SYS_USW_PKT_HEADER_LEN;
    if (pkt_len < 64)
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "IFA Invalid Packet Length %d.\n", pkt_len);
        return CTC_E_INVALID_MIN_FRAMESIZE;
    }

    sal_memset(&int_pkt_info, 0, sizeof(sys_int_pkt_info_t));

    (*p_usw_dtel_master[lchip]->g_sys_dtel_int_pkt_decode_cb)(lchip, p_pkt_rx, &int_pkt_info);

    rep_pkt = mem_malloc(MEM_DTEL_MODULE, pkt_len + 32 + ((CTC_DTEL_IFA_NODE_INITIATOR == p_usw_dtel_master[lchip]->ifa_session[int_pkt_info.int_session].node) ? 12 : 0));
    if (NULL == rep_pkt)
    {
        SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "No Memory.\n");
        return CTC_E_NO_MEMORY;
    }

    ret = _sys_usw_dtel_ifa_pkt_process(lchip, &int_pkt_info, p_pkt_rx->pkt_buf->data + p_pkt_rx->eth_hdr_len + SYS_USW_PKT_HEADER_LEN, pkt_len, &rep_pkt, &rep_pkt_len);
    if (ret < 0)
    {
        mem_free(rep_pkt);
        return ret;
    }

    if (!p_usw_dtel_master[lchip]->ifa_test_en)
    {
        ctc_pkt_rx_t pkt_rx;
        ctc_pkt_buf_t pkt_buf = {
                .data = rep_pkt,
                .len  = rep_pkt_len };
        sal_memcpy(&pkt_rx, p_pkt_rx, sizeof(ctc_pkt_rx_t));
        pkt_rx.pkt_len = rep_pkt_len;
        pkt_rx.pkt_buf = &pkt_buf;
        pkt_rx.buf_count = 1;
        pkt_rx.pkt_hdr_len = 0;
        pkt_rx.eth_hdr_len = 0;
        pkt_rx.stk_hdr_len = 0;
        pkt_rx.rx_info.session_id = int_pkt_info.int_session;
        SYS_DTEL_UNLOCK(lchip);
        CTC_ERROR_RETURN(sys_usw_packet_usr_rx_cb(lchip, &pkt_rx));
        SYS_DTEL_LOCK(lchip);
    }
    else
    {
        pkt_tx = mem_malloc(MEM_DTEL_MODULE, sizeof(ctc_pkt_tx_t));
        if (NULL == pkt_tx)
        {
            SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "No Memory.\n");
            mem_free(rep_pkt);
            return CTC_E_NO_MEMORY;
        }
        sal_memset(pkt_tx, 0, sizeof(ctc_pkt_tx_t));

        if (CTC_DTEL_IFA_NODE_TERMINATE == p_usw_dtel_master[lchip]->ifa_session[int_pkt_info.int_session].node)
        {
            /* packet tx & !ingress_mode & nexthop */
            CTC_SET_FLAG(pkt_tx->tx_info.flags, CTC_PKT_FLAG_NHID_VALID);
            pkt_tx->tx_info.ttl = 64;
            pkt_tx->tx_info.nhid = p_usw_dtel_master[lchip]->nhid[int_pkt_info.int_session];
        }
        else
        {
            /* packet tx & bypass all*/
            sys_usw_get_gchip_id(p_pkt_rx->lchip, &gchip);
            CTC_SET_FLAG(pkt_tx->tx_info.flags, CTC_PKT_FLAG_NH_OFFSET_BYPASS);
            pkt_tx->tx_info.dest_gport = CTC_MAP_LPORT_TO_GPORT(gchip, p_pkt_rx->rx_info.lport);
        }
        pkt_tx->mode = p_pkt_rx->mode;
        pkt_tx->lchip = lchip;
        pkt_tx->skb.data = rep_pkt;
        pkt_tx->skb.len = (rep_pkt_len < 64) ? 64 : rep_pkt_len;
        ret = sys_usw_packet_tx(lchip, pkt_tx);
        mem_free(pkt_tx);
    }
    mem_free(rep_pkt);
    return ret;
}


int32
sys_usw_dtel_dump_db(uint8 lchip, sal_file_t dump_db_fp,ctc_global_dump_db_t* p_dump_param)
{
    uint32 i = 0;
    uint32 j = 0;

    SYS_DTEL_INIT_CHECK(lchip);
    SYS_DTEL_LOCK(lchip);

    SYS_DUMP_DB_LOG(dump_db_fp, "\n");
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "# Dtel");
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "{");
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "Master config:");
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "---------------------------------------------------");
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:0x%x\n","postcard log bitmap", p_usw_dtel_master[lchip]->postcard_en);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:0x%x\n","inband log bitmap", p_usw_dtel_master[lchip]->inband_en);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","timeout", p_usw_dtel_master[lchip]->timeout);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","rep_id", p_usw_dtel_master[lchip]->rep_id);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-30s:%u\n","switch_id", p_usw_dtel_master[lchip]->switch_id);
    for (i = 0; i < CTC_DTEL_TIX_TYPE_MAX; i++)
    {
        if (p_usw_dtel_master[lchip]->tix_nh_id[i])
        {
            SYS_DUMP_DB_LOG(dump_db_fp, "tix[%3d]%-22s:%u\n", i ," nh id", p_usw_dtel_master[lchip]->tix_nh_id[i]);
        }
    }
    for (i = 0; i < CTC_DTEL_TSX_TYPE_MAX; i++)
    {
        if (p_usw_dtel_master[lchip]->tsx_nh_id[i])
        {
            SYS_DUMP_DB_LOG(dump_db_fp, "tsx[%3d]%-22s:%u\n", i ," nh id", p_usw_dtel_master[lchip]->tsx_nh_id[i]);
        }
    }
    for (i = 0; i < CTC_DTEL_TEX_TYPE_MAX; i++)
    {
        if (p_usw_dtel_master[lchip]->tex_nh_id[i])
        {
            SYS_DUMP_DB_LOG(dump_db_fp, "tex[%3d]%-22s:%u\n", i ," nh id", p_usw_dtel_master[lchip]->tex_nh_id[i]);
        }
    }
    for (i = 0; i < SYS_DTEL_INT_LOG_ID_NUM; i++)
    {
        SYS_DUMP_DB_LOG(dump_db_fp, "%-5s %-3u %-20s:", "log", i, "session bitmap");
        for (j = 0; j < SYS_DTEL_INT_SEN_BMP_LEN; j++)
        {
            SYS_DUMP_DB_LOG(dump_db_fp, "0x%x ", p_usw_dtel_master[lchip]->log_en[i][j]);
        }
        SYS_DUMP_DB_LOG(dump_db_fp, "\n");
    }

    for (i = 0; i < CTC_DTEL_INT_SINK_SESSION_NUM; i++)
    {
        SYS_DUMP_DB_LOG(dump_db_fp, "%-10s%-2u: ","session", i);
        SYS_DUMP_DB_LOG(dump_db_fp, "%s=%-10u ", "nh_id", p_usw_dtel_master[lchip]->nhid[i]);
        SYS_DUMP_DB_LOG(dump_db_fp, "%s=%-10u ", "rep_md_bits", p_usw_dtel_master[lchip]->rep_md_bits[i]);
        SYS_DUMP_DB_LOG(dump_db_fp, "\n");
    }

    SYS_DUMP_DB_LOG(dump_db_fp, "%-10s:%-2u \n","ifa-en", p_usw_dtel_master[lchip]->ifa_en);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-10s:%-2u \n","ifa-version", p_usw_dtel_master[lchip]->ifa_ver);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-10s:%-2u \n","ifa-eunit-en", p_usw_dtel_master[lchip]->ifa_eunit_en);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-10s:%-2u \n","ifa-internal-test", p_usw_dtel_master[lchip]->ifa_test_en);
    SYS_DUMP_DB_LOG(dump_db_fp, "%-10s:%-2u \n","ifa-protocol", p_usw_dtel_master[lchip]->ifa_protocol);

    if (p_usw_dtel_master[lchip]->ifa_session)
    {
        for (i = 0; i < CTC_DTEL_IFA_SESSION_NUM; i++)
        {
            SYS_DUMP_DB_LOG(dump_db_fp, "%-10s:%-2u \n","ifa-session", i);
            SYS_DUMP_DB_LOG(dump_db_fp, "    %s=%-10u \n", "node", p_usw_dtel_master[lchip]->ifa_session[i].node);
            SYS_DUMP_DB_LOG(dump_db_fp, "    %s=%-10u \n", "gns", p_usw_dtel_master[lchip]->ifa_session[i].gns);
            SYS_DUMP_DB_LOG(dump_db_fp, "    %s=%-10u \n", "hop_limit", p_usw_dtel_master[lchip]->ifa_session[i].hop_limit);
            SYS_DUMP_DB_LOG(dump_db_fp, "    %s=%-10u \n", "max_length", p_usw_dtel_master[lchip]->ifa_session[i].max_length);
            SYS_DUMP_DB_LOG(dump_db_fp, "    %s=0x%-8x \n", "req_vec", p_usw_dtel_master[lchip]->ifa_session[i].req_vec);
            SYS_DUMP_DB_LOG(dump_db_fp, "\n");
        }
    }
    SYS_DUMP_DB_LOG(dump_db_fp, "%s\n", "}");
    SYS_DTEL_UNLOCK(lchip);

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_dtel_wb_sync(uint8 lchip, uint32 app_id)
{
    int32  ret = CTC_E_NONE;
    uint8 idx = 0;
    ctc_wb_data_t wb_data;
    sys_wb_dtel_master_t* p_wb_dtel_master = NULL;

    SYS_DTEL_INIT_CHECK(lchip);
    sal_memset(&wb_data, 0, sizeof(ctc_wb_data_t));
    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);

    SYS_DTEL_LOCK(lchip);
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_DTEL_SUBID_MASTER)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_dtel_master_t, CTC_FEATURE_DTEL, SYS_WB_APPID_DTEL_SUBID_MASTER);
        p_wb_dtel_master = (sys_wb_dtel_master_t*)wb_data.buffer;
        p_wb_dtel_master->lchip = lchip;
        p_wb_dtel_master->version = SYS_WB_VERSION_DTEL;
        p_wb_dtel_master->rep_id = p_usw_dtel_master[lchip]->rep_id;
        p_wb_dtel_master->switch_id = p_usw_dtel_master[lchip]->switch_id;
        p_wb_dtel_master->postcard_en = p_usw_dtel_master[lchip]->postcard_en;
        p_wb_dtel_master->inband_en = p_usw_dtel_master[lchip]->inband_en;
        p_wb_dtel_master->rsv = 0;
        p_wb_dtel_master->dscp = p_usw_dtel_master[lchip]->dscp;
        for (idx = 0; idx < SYS_WB_DTEL_TIX_NH_NUM; idx++)
        {
            p_wb_dtel_master->tix_nh_id[idx] = p_usw_dtel_master[lchip]->tix_nh_id[idx];
        }
        for (idx = 0; idx < SYS_WB_DTEL_TSX_NH_NUM; idx++)
        {
            p_wb_dtel_master->tsx_nh_id[idx] = p_usw_dtel_master[lchip]->tsx_nh_id[idx];
        }
        for (idx = 0; idx < SYS_WB_DTEL_TEX_NH_NUM; idx++)
        {
            p_wb_dtel_master->tex_nh_id[idx] = p_usw_dtel_master[lchip]->tex_nh_id[idx];
        }
        sal_memcpy(p_wb_dtel_master->nhid, p_usw_dtel_master[lchip]->nhid, sizeof(p_usw_dtel_master[lchip]->nhid));
        sal_memcpy(p_wb_dtel_master->log_en, p_usw_dtel_master[lchip]->log_en, sizeof(p_usw_dtel_master[lchip]->log_en));
        sal_memcpy(p_wb_dtel_master->rep_md_bits, p_usw_dtel_master[lchip]->rep_md_bits, sizeof(p_usw_dtel_master[lchip]->rep_md_bits));
        p_wb_dtel_master->ifa_ver = p_usw_dtel_master[lchip]->ifa_ver;
        p_wb_dtel_master->ifa_en = p_usw_dtel_master[lchip]->ifa_en;
        p_wb_dtel_master->ifa_protocol = p_usw_dtel_master[lchip]->ifa_protocol;
        p_wb_dtel_master->ifa_eunit_en = p_usw_dtel_master[lchip]->ifa_eunit_en;
        if (p_usw_dtel_master[lchip]->ifa_session)
        {
            p_wb_dtel_master->ifa_session_valid = 1;
            sal_memcpy(p_wb_dtel_master->ifa_session, p_usw_dtel_master[lchip]->ifa_session, sizeof(p_wb_dtel_master->ifa_session));
        }
        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_DTEL, SYS_WB_APPID_DTEL_SUBID_MASTER);
    }

done:
    SYS_DTEL_UNLOCK(lchip);
    CTC_WB_FREE_BUFFER(wb_data.buffer);
    return ret;
}

STATIC int32
_sys_usw_dtel_wb_restore(uint8 lchip)
{
    int32  ret = CTC_E_NONE;
    uint8 idx = 0;
    ctc_wb_query_t wb_query;
    sys_wb_dtel_master_t wb_dtel_master;
    sal_memset(&wb_query, 0, sizeof(ctc_wb_query_t));
    sal_memset(&wb_dtel_master, 0, sizeof(sys_wb_dtel_master_t));
    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);

    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_dtel_master_t, CTC_FEATURE_DTEL, SYS_WB_APPID_DTEL_SUBID_MASTER);
    CTC_ERROR_GOTO(ctc_wb_query_entry(&wb_query), ret, exit);
    if ((wb_query.valid_cnt != 1) || (wb_query.is_end != 1))
    {
        CTC_WB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "query dtel master error! valid_cnt: %d, is_end: %d.\n", wb_query.valid_cnt, wb_query.is_end);
        CTC_ERROR_GOTO(CTC_E_INVALID_CONFIG, ret, exit);
    }
    sal_memcpy((uint8 *)&wb_dtel_master, (uint8 *)wb_query.buffer, wb_query.key_len + wb_query.data_len);
    if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_DTEL, wb_dtel_master.version))
    {
        CTC_ERROR_GOTO(CTC_E_VERSION_MISMATCH, ret, exit);
    }
    p_usw_dtel_master[lchip]->rep_id = wb_dtel_master.rep_id;
    p_usw_dtel_master[lchip]->switch_id = wb_dtel_master.switch_id;
    p_usw_dtel_master[lchip]->postcard_en = wb_dtel_master.postcard_en;
    p_usw_dtel_master[lchip]->inband_en = wb_dtel_master.inband_en;
    p_usw_dtel_master[lchip]->dscp = wb_dtel_master.dscp;
    p_usw_dtel_master[lchip]->tsx_mac_stats_en = wb_dtel_master.tsx_mac_stats_en;
    if (p_usw_dtel_master[lchip]->tsx_mac_stats_en)
    {
        sys_usw_dma_set_chan_en(lchip, SYS_DMA_PORT_STATS_CHAN_ID, 0);
    }
    sal_memcpy(p_usw_dtel_master[lchip]->nhid, wb_dtel_master.nhid, sizeof(p_usw_dtel_master[lchip]->nhid));
    sal_memcpy(p_usw_dtel_master[lchip]->log_en, wb_dtel_master.log_en, sizeof(p_usw_dtel_master[lchip]->log_en));
    sal_memcpy(p_usw_dtel_master[lchip]->rep_md_bits, wb_dtel_master.rep_md_bits, sizeof(p_usw_dtel_master[lchip]->rep_md_bits));
    p_usw_dtel_master[lchip]->ifa_ver = wb_dtel_master.ifa_ver;
    p_usw_dtel_master[lchip]->ifa_en = wb_dtel_master.ifa_en;
    p_usw_dtel_master[lchip]->ifa_protocol = wb_dtel_master.ifa_protocol;
    p_usw_dtel_master[lchip]->ifa_eunit_en = wb_dtel_master.ifa_eunit_en;
    SYS_CB(SYS_CB_ACL_SET_IFA_VER, lchip, p_usw_dtel_master[lchip]->ifa_ver);
    for (idx = 0; idx < SYS_WB_DTEL_TIX_NH_NUM; idx++)
    {
        p_usw_dtel_master[lchip]->tix_nh_id[idx] = wb_dtel_master.tix_nh_id[idx];
    }
    for (idx = 0; idx < SYS_WB_DTEL_TSX_NH_NUM; idx++)
    {
        p_usw_dtel_master[lchip]->tsx_nh_id[idx] = wb_dtel_master.tsx_nh_id[idx];
    }
    for (idx = 0; idx < SYS_WB_DTEL_TEX_NH_NUM; idx++)
    {
        p_usw_dtel_master[lchip]->tex_nh_id[idx] = wb_dtel_master.tex_nh_id[idx];
    }
    if (wb_dtel_master.ifa_session_valid)
    {
        p_usw_dtel_master[lchip]->ifa_session = mem_malloc(MEM_DTEL_MODULE, CTC_DTEL_IFA_SESSION_NUM * sizeof(sys_dtel_ifa_session_t));
        if (NULL == p_usw_dtel_master[lchip]->ifa_session)
        {
            CTC_ERROR_GOTO(CTC_E_NO_MEMORY, ret, exit);
        }
        sal_memcpy(p_usw_dtel_master[lchip]->ifa_session, wb_dtel_master.ifa_session, sizeof(wb_dtel_master.ifa_session));
    }

exit:
    CTC_WB_FREE_BUFFER(wb_query.buffer);
    return ret;
}
STATIC int32
_sys_usw_dtel_wb_init(uint8 lchip)
{
   ctc_wb_appid_t  appid;
   sal_memset(&appid,0,sizeof(appid));

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_DTEL, SYS_WB_APPID_DTEL_SUBID_MASTER) ;
   appid.entry_num = 1;
   appid.entry_size  = sizeof(sys_wb_dtel_master_t);
   appid.rt_en = 0;
   ctc_wb_add_appid( lchip, &appid);
   return 0;
}
int32
sys_usw_dtel_ifa_test_en(uint8 lchip, uint8 enable)
{
    SYS_DTEL_INIT_CHECK(lchip);
    SYS_DTEL_LOCK(lchip);
    p_usw_dtel_master[lchip]->ifa_test_en = enable ? 1 : 0;
    SYS_DTEL_UNLOCK(lchip);
    return CTC_E_NONE;
}

#define ______DTEL_RX_CALL_BACK______
int32
sys_dtel_pkt_rx_dispatch(uint8 lchip, ctc_pkt_rx_t* p_pkt_rx)
{
    /* To create rep task only once */
    _sys_usw_dtel_int_init_db(lchip);

    if (!p_usw_dtel_master[lchip]->ifa_en)
    {
        SYS_DTEL_SINK_LOCK(lchip);
        _sys_usw_dtel_int_pkt_rx(p_pkt_rx);
        SYS_DTEL_SINK_UNLOCK(lchip);
    }
    else
    {
        SYS_DTEL_LOCK(lchip);
        _sys_usw_dtel_ifa_pkt_rx(p_pkt_rx);
        SYS_DTEL_UNLOCK(lchip);
    }
    return CTC_E_NONE;
}

#define ______SYS_API______
int32
sys_usw_dtel_free_task(uint8 lchip)
{
    if (NULL != p_usw_dtel_master[lchip] && NULL != p_usw_dtel_master[lchip]->sink_sem)
    {
        sal_sem_give(p_usw_dtel_master[lchip]->sink_sem);
    }
    return CTC_E_NONE;
}

uint8
sys_usw_tsx_get_mac_stats_en(uint8 lchip)
{
#if defined E_UNIT && (FEATURE_MODE == 0)
    if (!p_usw_dtel_master[lchip])
    {
        return 0;
    }
    if (p_usw_dtel_master[lchip]->tsx_mac_stats_en)
    {
        return 1;
    }
#endif
    return 0;
}

int32
sys_usw_dtel_set_property(uint8 lchip, ctc_dtel_property_t type, void* value)
{
    int32 ret = CTC_E_NONE;
#if defined E_UNIT && (FEATURE_MODE == 0)
    uint8 ifa_eunit_en = 0;
#endif
    SYS_DTEL_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(value);

    SYS_DTEL_LOCK(lchip);
    ret = _sys_usw_dtel_set_property(lchip, type, value);
#if defined E_UNIT && (FEATURE_MODE == 0)
    ifa_eunit_en = p_usw_dtel_master[lchip]->ifa_eunit_en;
#endif
    SYS_DTEL_UNLOCK(lchip);
    if (ret < 0)
    {
        return ret;
    }
#if defined E_UNIT && (FEATURE_MODE == 0)
    /* map cpu reason */
    if (CTC_DTEL_IFA_EN == type || CTC_DTEL_INT_EN == type)
    {
        ctc_qos_queue_cfg_t que_cfg;
        uint32 val = *(uint32*)value;
        ctc_qos_shape_t shape;
        uint8 gchip = 0;

        sal_memset(&shape, 0, sizeof(ctc_qos_shape_t));
        sal_memset(&que_cfg, 0, sizeof(que_cfg));
        sys_usw_get_gchip_id(lchip, &gchip);
        if (DRV_FROM_AT(lchip))
        {
            if (CTC_DTEL_IFA_EN == type)
            {
                return CTC_E_NONE;
            }
            que_cfg.value.reason_dest.cpu_reason = CTC_PKT_CPU_REASON_DTEL_REPORT;
            que_cfg.type = CTC_QOS_QUEUE_CFG_QUEUE_REASON_DEST;
            que_cfg.value.reason_dest.dest_type = val ? CTC_PKT_CPU_REASON_TO_LOCAL_CPU : CTC_PKT_CPU_REASON_TO_DROP;
            CTC_ERROR_RETURN(sys_usw_qos_set_queue(lchip, &que_cfg));
            sal_memset(&que_cfg, 0, sizeof(que_cfg));
            que_cfg.value.reason_map.reason_group = SYS_DTEL_REPORT_CPU_REASON_SUB_QUE_ID >> 3;
            que_cfg.value.reason_map.queue_id = SYS_DTEL_REPORT_CPU_REASON_SUB_QUE_ID & 0x7;
            shape.shape.queue_shape.enable = 0;
            if(val)
            {
                que_cfg.type = CTC_QOS_QUEUE_CFG_QUEUE_REASON_MAP;
                que_cfg.value.reason_map.cpu_reason = CTC_PKT_CPU_REASON_DTEL_REPORT;
                CTC_ERROR_RETURN(sys_usw_qos_set_queue(lchip, &que_cfg));
                shape.shape.queue_shape.queue.queue_type = CTC_QUEUE_TYPE_EXCP_CPU;
                shape.shape.queue_shape.queue.cpu_reason = CTC_PKT_CPU_REASON_DTEL_REPORT;
                shape.type = CTC_QOS_SHAPE_QUEUE;
                CTC_ERROR_RETURN(sys_usw_qos_set_shape(lchip, &shape));
            }
        }
        else
        {
            que_cfg.type = CTC_QOS_QUEUE_CFG_QUEUE_REASON_DEST;
            que_cfg.value.reason_dest.cpu_reason = CTC_PKT_CPU_REASON_DTEL_REPORT;
            if (CTC_DTEL_IFA_EN == type && ifa_eunit_en)
            {
                que_cfg.value.reason_dest.dest_type = val ? CTC_PKT_CPU_REASON_TO_LOCAL_PORT : CTC_PKT_CPU_REASON_TO_DROP;
                que_cfg.value.reason_dest.dest_port = val ? CTC_MAP_LPORT_TO_GPORT(gchip, SYS_RSV_PORT_EUNIT0_ID) : 0;

                if (val)
                {
                    CTC_ERROR_RETURN(sys_usw_brguc_nh_create(lchip, CTC_MAP_LPORT_TO_GPORT(gchip, SYS_RSV_PORT_EUNIT0_ID), CTC_NH_PARAM_BRGUC_SUB_TYPE_BASIC));
                }
                else
                {
                    sys_usw_brguc_nh_delete(lchip, CTC_MAP_LPORT_TO_GPORT(gchip, SYS_RSV_PORT_EUNIT0_ID));
                }
                shape.shape.port_shape.enable = 1;
                shape.shape.port_shape.pir = 100000; /* 100M */
                shape.shape.port_shape.pbs = 0xFFFFFFFF;
                CTC_ERROR_RETURN(sys_usw_qos_set_queue(lchip, &que_cfg));
            }
            else
            {
                shape.shape.port_shape.enable = 0;
                que_cfg.value.reason_dest.dest_type = val ? CTC_PKT_CPU_REASON_TO_LOCAL_CPU : CTC_PKT_CPU_REASON_TO_DROP;
                CTC_ERROR_RETURN(sys_usw_qos_set_queue(lchip, &que_cfg));
                if (val)
                {
                    que_cfg.type = CTC_QOS_QUEUE_CFG_QUEUE_REASON_MAP;
                    que_cfg.value.reason_map.cpu_reason = CTC_PKT_CPU_REASON_DTEL_REPORT;
                    que_cfg.value.reason_map.reason_group = SYS_DTEL_REPORT_CPU_REASON_SUB_QUE_ID >> 3;
                    que_cfg.value.reason_map.queue_id = SYS_DTEL_REPORT_CPU_REASON_SUB_QUE_ID & 0x7;
                    CTC_ERROR_RETURN(sys_usw_qos_set_queue(lchip, &que_cfg));
                }
            }
            shape.type = CTC_QOS_SHAPE_PORT;
            shape.shape.port_shape.gport = CTC_MAP_LPORT_TO_GPORT(gchip, SYS_RSV_PORT_EUNIT0_ID);
            CTC_ERROR_RETURN(sys_usw_qos_set_shape(lchip, &shape));
        }
    }
    else if (CTC_DTEL_TEX_CFG == type)
    {
        ctc_dtel_tex_cfg_t* tex_cfg = (ctc_dtel_tex_cfg_t*)value;
        if (CTC_DTEL_TEX_DROP_EVENT == tex_cfg->type)
        {
            CTC_ERROR_RETURN(_sys_usw_dtel_drop_pkt_redirect_eunit(lchip, tex_cfg->nh_id ? 1 : 0));
        }
    }
#endif

    return CTC_E_NONE;
}

int32
sys_usw_dtel_get_property(uint8 lchip,ctc_dtel_property_t type,void *value)
{
    int32 ret = CTC_E_NONE;
    SYS_DTEL_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(value);

    SYS_DTEL_LOCK(lchip);
    ret = _sys_usw_dtel_get_property(lchip, type, value);
    SYS_DTEL_UNLOCK(lchip);
    return ret;
}


int32
sys_usw_dtel_set_int_cfg(uint8 lchip, ctc_dtel_int_cfg_t *p_cfg)
{
    int32 ret = CTC_E_NONE;

    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_DTEL_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_cfg);
    CTC_MAX_VALUE_CHECK(p_cfg->session_id, CTC_DTEL_INT_SINK_SESSION_NUM-1);

    SYS_DTEL_LOCK(lchip);
    ret = _sys_usw_dtel_set_int_cfg(lchip, p_cfg);
    SYS_DTEL_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_dtel_get_int_cfg(uint8 lchip, ctc_dtel_int_cfg_t *p_cfg)
{
    int32 ret = CTC_E_NONE;

    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_DTEL_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_cfg);
    CTC_MAX_VALUE_CHECK(p_cfg->session_id, CTC_DTEL_INT_SINK_SESSION_NUM-1);

    SYS_DTEL_LOCK(lchip);
    ret = _sys_usw_dtel_get_int_cfg(lchip, p_cfg);
    SYS_DTEL_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_dtel_get_ifa_cfg(uint8 lchip, ctc_dtel_ifa_cfg_t *p_cfg)
{
    int32 ret = CTC_E_NONE;

    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_DTEL_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_cfg);
    CTC_MAX_VALUE_CHECK(p_cfg->session_id, CTC_DTEL_INT_SINK_SESSION_NUM-1);

    SYS_DTEL_LOCK(lchip);
    ret = _sys_usw_dtel_get_ifa_cfg(lchip, p_cfg);
    SYS_DTEL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_dtel_set_ifa_cfg(uint8 lchip, ctc_dtel_ifa_cfg_t *p_cfg)
{
    int32 ret = CTC_E_NONE;

    SYS_DTEL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_DTEL_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_cfg);
    CTC_MAX_VALUE_CHECK(p_cfg->session_id, CTC_DTEL_INT_SINK_SESSION_NUM-1);
    CTC_MAX_VALUE_CHECK(p_cfg->node, CTC_DTEL_IFA_NODE_MAX - 1);

    SYS_DTEL_LOCK(lchip);
    ret = _sys_usw_dtel_set_ifa_cfg(lchip, p_cfg);
    SYS_DTEL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_dtel_init(uint8 lchip, ctc_dtel_global_cfg_t* p_glb_cfg)
{
    int32  ret = CTC_E_NONE;
    DsIntEditCtl_m epe_edit;
    uint32 cmd = 0;

    if (NULL != p_usw_dtel_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT(lchip, p_usw_dtel_master, CTC_FEATURE_DTEL);
    CTC_ERROR_RETURN(sys_usw_global_set_int_en(lchip, TRUE));
    MALLOC_ZERO(MEM_DTEL_MODULE, p_usw_dtel_master[lchip], sizeof(sys_dtel_master_t));
    CTC_ERROR_RETURN(NULL == p_usw_dtel_master[lchip]? CTC_E_NO_MEMORY: CTC_E_NONE);

    CTC_ERROR_GOTO(sys_usw_get_gchip_id(lchip, &p_usw_dtel_master[lchip]->chip_id), ret, error0);

    sal_mutex_create(&p_usw_dtel_master[lchip]->mutex);
    CTC_ERROR_GOTO(NULL == p_usw_dtel_master[lchip]->mutex? CTC_E_NO_MEMORY: CTC_E_NONE, ret, error0);
    p_usw_dtel_master[lchip]->switch_id = 1;
    cmd = DRV_IOR(DsIntEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));
    SetDsIntEditCtl(V, switchInfo0_f, &epe_edit, 1);
    SetDsIntEditCtl(V, switchInfo1_f, &epe_edit, 1);
    cmd = DRV_IOW(DsIntEditCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_edit));

    p_usw_dtel_master[lchip]->timeout = 60;/*1 min*/
    p_usw_dtel_master[lchip]->dscp = 0;
    if (p_glb_cfg)
    {
        p_usw_dtel_master[lchip]->ifa_eunit_en = p_glb_cfg->ifa_eunit_en;
    }

    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_DTEL_PKT_RX, sys_dtel_pkt_rx_dispatch), ret, error1);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_TSX_GET_MAC_STATS_EN, sys_usw_tsx_get_mac_stats_en), ret, error1);
    CTC_ERROR_GOTO(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_DTEL,SYS_WB_APPID_DTEL_SUBID_MAX, _sys_usw_dtel_wb_sync), ret, error1);
    /* dump-db register */
    CTC_ERROR_GOTO(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_DTEL, sys_usw_dtel_dump_db), ret, error1);
    if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
    {
        p_usw_dtel_master[lchip]->g_sys_dtel_int_pkt_decode_cb = _sys_tmm_dtel_int_pkt_decode;
    }
    else if(DRV_FROM_AT(lchip))
    {
        p_usw_dtel_master[lchip]->g_sys_dtel_int_pkt_decode_cb = _sys_at_dtel_int_pkt_decode;
    }

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        CTC_ERROR_GOTO(_sys_usw_dtel_wb_restore(lchip), ret, error1);
    }

    if (CTC_WB_ENABLE(lchip))
    {
        _sys_usw_dtel_wb_init(lchip);
    }
    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_DTEL);

    return CTC_E_NONE;


error1:
    sal_mutex_destroy(p_usw_dtel_master[lchip]->mutex);
error0:
    mem_free(p_usw_dtel_master[lchip]);
    return ret;
}

int32
sys_usw_dtel_deinit(uint8 lchip)
{
    LCHIP_CHECK(lchip);
    if (NULL == p_usw_dtel_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT(lchip, p_usw_dtel_master, CTC_FEATURE_DTEL);
    SYS_CB_REGISTER(lchip, SYS_CB_DTEL_PKT_RX, NULL);
    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_DTEL,0, NULL);
    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_DTEL, NULL);
    _sys_usw_dtel_int_deinit_db(lchip);
    sal_mutex_destroy(p_usw_dtel_master[lchip]->mutex);
    mem_free(p_usw_dtel_master[lchip]);
    sys_usw_global_set_int_en(lchip, FALSE);
    return CTC_E_NONE;
}

#endif


